Félix MIELCAREK 2 years ago
parent a9488bfce6
commit 3252de5cb0

@ -0,0 +1,6 @@
@typeparam TItem
<div class="card text-center">
@CardHeader(Item)
@CardBody(Item)
@CardFooter
</div>

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Components;
namespace BlazorApp.Components;
public partial class Card<TItem>
{
[Parameter]
public RenderFragment<TItem> CardBody { get; set; }
[Parameter]
public RenderFragment CardFooter { get; set; }
[Parameter]
public RenderFragment<TItem> CardHeader { get; set; }
[Parameter]
public TItem Item { get; set; }
}

@ -0,0 +1,50 @@
<CascadingValue Value="@this">
<div class="container">
<div class="row">
<div class="col-6">
<div>Available items:</div>
<div>
<div class="css-grid">
@foreach (var item in Items)
{
<CraftingItem Item="item" NoDrop="true" />
}
</div>
</div>
</div>
<div class="col-6">
<div>Recipe</div>
<div>
<div class="css-recipe">
<CraftingItem Index="0" />
<CraftingItem Index="1" />
<CraftingItem Index="2" />
<CraftingItem Index="3" />
<CraftingItem Index="4" />
<CraftingItem Index="5" />
<CraftingItem Index="6" />
<CraftingItem Index="7" />
<CraftingItem Index="8" />
</div>
</div>
<div>Result</div>
<div>
<CraftingItem Item="RecipeResult" />
</div>
</div>
<div class="col-12">
<div>Actions</div>
<div class="actions" id="actions">
</div>
</div>
</div>
</div>
</CascadingValue>

@ -0,0 +1,80 @@
using BlazorApp.Models;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
namespace BlazorApp.Components
{
public partial class Crafting
{
private Item _recipeResult;
public Crafting()
{
Actions = new ObservableCollection<CraftingAction>();
Actions.CollectionChanged += OnActionsCollectionChanged;
this.RecipeItems = new List<Item> { null, null, null, null, null, null, null, null, null };
}
public ObservableCollection<CraftingAction> Actions { get; set; }
public Item CurrentDragItem { get; set; }
[Parameter]
public List<Item> Items { get; set; }
public List<Item> RecipeItems { get; set; }
public Item RecipeResult
{
get => this._recipeResult;
set
{
if (this._recipeResult == value)
{
return;
}
this._recipeResult = value;
this.StateHasChanged();
}
}
[Parameter]
public List<CraftingRecipe> Recipes { get; set; }
/// <summary>
/// Gets or sets the java script runtime.
/// </summary>
[Inject]
internal IJSRuntime JavaScriptRuntime { get; set; }
public void CheckRecipe()
{
RecipeResult = null;
// Get the current model
var currentModel = string.Join("|", this.RecipeItems.Select(s => s != null ? s.Name : string.Empty));
this.Actions.Add(new CraftingAction { Action = $"Items : {currentModel}" });
foreach (var craftingRecipe in Recipes)
{
// Get the recipe model
var recipeModel = string.Join("|", craftingRecipe.Have.SelectMany(s => s));
this.Actions.Add(new CraftingAction { Action = $"Recipe model : {recipeModel}" });
if (currentModel == recipeModel)
{
RecipeResult = craftingRecipe.Give;
}
}
}
private void OnActionsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
JavaScriptRuntime.InvokeVoidAsync("Crafting.AddActions", e.NewItems);
}
}
}

@ -0,0 +1,19 @@
.css-grid {
grid-template-columns: repeat(4,minmax(0,1fr));
gap: 10px;
display: grid;
width: 286px;
}
.css-recipe {
grid-template-columns: repeat(3,minmax(0,1fr));
gap: 10px;
display: grid;
width: 212px;
}
.actions {
border: 1px solid black;
height: 250px;
overflow: scroll;
}

@ -0,0 +1,16 @@
window.Crafting =
{
AddActions: function (data) {
data.forEach(element => {
var div = document.createElement('div');
div.innerHTML = 'Action: ' + element.action + ' - Index: ' + element.index;
if (element.item) {
div.innerHTML += ' - Item Name: ' + element.item.name;
}
document.getElementById('actions').appendChild(div);
});
}
}

@ -0,0 +1,11 @@
using BlazorApp.Models;
namespace BlazorApp.Components
{
public class CraftingAction
{
public string Action { get; set; }
public int Index { get; set; }
public Item Item { get; set; }
}
}

@ -0,0 +1,13 @@
<div class="item"
ondragover="event.preventDefault();"
draggable="true"
@ondragstart="@OnDragStart"
@ondrop="@OnDrop"
@ondragenter="@OnDragEnter"
@ondragleave="@OnDragLeave">
@if (Item != null)
{
@Item.DisplayName
}
</div>

@ -0,0 +1,64 @@
using BlazorApp.Models;
using Blazorise;
using Microsoft.AspNetCore.Components;
namespace BlazorApp.Components
{
public partial class CraftingItem
{
[Parameter]
public int Index { get; set; }
[Parameter]
public Item Item { get; set; }
[Parameter]
public bool NoDrop { get; set; }
[CascadingParameter]
public Crafting Parent { get; set; }
internal void OnDragEnter()
{
if (NoDrop)
{
return;
}
Parent.Actions.Add(new CraftingAction { Action = "Drag Enter", Item = this.Item, Index = this.Index });
}
internal void OnDragLeave()
{
if (NoDrop)
{
return;
}
Parent.Actions.Add(new CraftingAction { Action = "Drag Leave", Item = this.Item, Index = this.Index });
}
internal void OnDrop()
{
if (NoDrop)
{
return;
}
this.Item = Parent.CurrentDragItem;
Parent.RecipeItems[this.Index] = this.Item;
Parent.Actions.Add(new CraftingAction { Action = "Drop", Item = this.Item, Index = this.Index });
// Check recipe
Parent.CheckRecipe();
}
private void OnDragStart()
{
Parent.CurrentDragItem = this.Item;
Parent.Actions.Add(new CraftingAction { Action = "Drag Start", Item = this.Item, Index = this.Index });
}
}
}

@ -0,0 +1,6 @@
.item {
width: 64px;
height: 64px;
border: 1px solid;
overflow: hidden;
}

@ -0,0 +1,10 @@
using BlazorApp.Models;
namespace BlazorApp.Components
{
public class CraftingRecipe
{
public Item Give { get; set; }
public List<List<string>> Have { get; set; }
}
}

@ -0,0 +1,11 @@
@typeparam TItem
<div>
@if ((Items?.Count ?? 0) != 0)
{
@foreach (var item in Items)
{
@ShowTemplate(item);
}
}
</div>

@ -0,0 +1,13 @@
using Microsoft.AspNetCore.Components;
namespace BlazorApp.Components
{
public partial class ShowItems<TItem>
{
[Parameter]
public List<TItem> Items { get; set; }
[Parameter]
public RenderFragment<TItem> ShowTemplate { get; set; }
}
}

@ -0,0 +1,8 @@
<h3>TestRenderFragment</h3>
@code {
[Parameter]
public RenderFragment ChildContent { get; set; }
}
@ChildContent

@ -0,0 +1,31 @@
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
/// <summary>
/// The culture controller.
/// </summary>
[Route("[controller]/[action]")]
public class CultureController : Controller
{
/// <summary>
/// Sets the culture.
/// </summary>
/// <param name="culture">The culture.</param>
/// <param name="redirectUri">The redirect URI.</param>
/// <returns>
/// The action result.
/// </returns>
public IActionResult SetCulture(string culture, string redirectUri)
{
if (culture != null)
{
// Define a cookie with the selected culture
this.HttpContext.Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(
new RequestCulture(culture)));
}
return this.LocalRedirect(redirectUri);
}
}

@ -0,0 +1,8 @@
namespace BlazorApp.Models;
public class Cake
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Cost { get; set; }
}

@ -1,4 +1,6 @@
@page "/" @page "/"
@using System.Globalization
@using BlazorApp.Components
<PageTitle>Index</PageTitle> <PageTitle>Index</PageTitle>
@ -7,3 +9,42 @@
Welcome to your new app. Welcome to your new app.
<SurveyPrompt Title="How is Blazor working for you?" /> <SurveyPrompt Title="How is Blazor working for you?" />
<p>
<b>CurrentCulture</b>: @CultureInfo.CurrentCulture
</p>
<Card Item="CakeItem">
<CardHeader Context="headContext">
<div class="card-header">
Cake Token Number - @headContext.Id
</div>
</CardHeader>
<CardBody Context="bodyContext">
<div class="card-body">
<div>@bodyContext.Name</div>
<div>$ @bodyContext.Cost</div>
</div>
</CardBody>
</Card>
<ShowItems Items="Cakes" >
<ShowTemplate Context="CakeContext">
<div class="card text-center">
<div class="card-header">
Cake Token Id - @CakeContext.Id
</div>
<div class="card-body">
<h5 class="card-title">@CakeContext.Name</h5>
<p class="card-text">Price $@CakeContext.Cost</p>
</div>
<div class="card-footer text-muted">
Click Here
</div>
</div>
</ShowTemplate>
</ShowItems>
<TestRenderFragment>
<div>Content of my TestRenderFragment</div>
</TestRenderFragment>

@ -0,0 +1,35 @@
namespace BlazorApp.Pages;
using BlazorApp.Models;
public partial class Index
{
private Cake CakeItem = new Cake
{
Id = 1,
Name = "Black Forest",
Cost = 50
};
public List<Cake> Cakes { get; set; }
protected override Task OnAfterRenderAsync(bool firstRender)
{
LoadCakes();
StateHasChanged();
return base.OnAfterRenderAsync(firstRender);
}
public void LoadCakes()
{
Cakes = new List<Cake>
{
// items hidden for display purpose
new Cake
{
Id = 1,
Name = "Red Velvet",
Cost = 60
},
};
}
}

@ -1,7 +1,7 @@
@page "/list" @page "/list"
@using BlazorApp.Models @using BlazorApp.Models
<h3>List</h3> <h3>@Localizer["Title"]</h3>
<div> <div>
<NavLink class="btn btn-primary" href="Add" Match="NavLinkMatch.All"> <NavLink class="btn btn-primary" href="Add" Match="NavLinkMatch.All">

@ -16,6 +16,9 @@ public partial class List
private int totalItem; private int totalItem;
[Inject]
public IStringLocalizer<List> Localizer { get; set; }
[Inject] [Inject]
public IDataService DataService { get; set; } public IDataService DataService { get; set; }

@ -0,0 +1,29 @@
@page "/pets1"
<h1>Pets</h1>
<TableTemplate Items="pets" Context="pet">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td>@pet.PetId</td>
<td>@pet.Name</td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
new Pet { PetId = 4, Name = "Salem Saberhagen" },
new Pet { PetId = 7, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}

@ -0,0 +1,29 @@
@page "/pets2"
<h1>Pets</h1>
<TableTemplate Items="pets">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate Context="pet">
<td>@pet.PetId</td>
<td>@pet.Name</td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
new Pet { PetId = 4, Name = "Salem Saberhagen" },
new Pet { PetId = 7, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}

@ -0,0 +1,29 @@
@page "/pets3"
<h1>Pets</h1>
<TableTemplate Items="pets">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td>@context.PetId</td>
<td>@context.Name</td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
new Pet { PetId = 4, Name = "Salem Saberhagen" },
new Pet { PetId = 7, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}

@ -0,0 +1,29 @@
@page "/pets4"
<h1>Pets</h1>
<TableTemplate Items="pets" TItem="Pet">
<TableHeader>
<th>ID</th>
<th>Name</th>
</TableHeader>
<RowTemplate>
<td>@context.PetId</td>
<td>@context.Name</td>
</RowTemplate>
</TableTemplate>
@code {
private List<Pet> pets = new()
{
new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
new Pet { PetId = 4, Name = "Salem Saberhagen" },
new Pet { PetId = 7, Name = "K-9" }
};
private class Pet
{
public int PetId { get; set; }
public string? Name { get; set; }
}
}

@ -5,6 +5,9 @@ using Blazorise;
using Blazorise.Bootstrap; using Blazorise.Bootstrap;
using Blazorise.Icons.FontAwesome; using Blazorise.Icons.FontAwesome;
using Blazored.Modal; using Blazored.Modal;
using Microsoft.AspNetCore.Localization;
using System.Globalization;
using Microsoft.Extensions.Options;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
@ -21,6 +24,22 @@ builder.Services
builder.Services.AddScoped<IDataService, DataLocalService>(); builder.Services.AddScoped<IDataService, DataLocalService>();
builder.Services.AddBlazoredModal(); builder.Services.AddBlazoredModal();
// Add the controller of the app
builder.Services.AddControllers();
// Add the localization to the app and specify the resources path
builder.Services.AddLocalization(opts => { opts.ResourcesPath = "Resources"; });
// Configure the localtization
builder.Services.Configure<RequestLocalizationOptions>(options =>
{
// Set the default culture of the web site
options.DefaultRequestCulture = new RequestCulture(new CultureInfo("en-US"));
// Declare the supported culture
options.SupportedCultures = new List<CultureInfo> { new CultureInfo("en-US"), new CultureInfo("fr-FR") };
options.SupportedUICultures = new List<CultureInfo> { new CultureInfo("en-US"), new CultureInfo("fr-FR") };
});
var app = builder.Build(); var app = builder.Build();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
@ -36,7 +55,20 @@ app.UseHttpsRedirection();
app.UseStaticFiles(); app.UseStaticFiles();
app.UseRouting(); app.UseRouting();
// Get the current localization options
var options = ((IApplicationBuilder)app).ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
if (options?.Value != null)
{
// use the default localization
app.UseRequestLocalization(options.Value);
}
// Add the controller to the endpoint
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.MapBlazorHub(); app.MapBlazorHub();
app.MapFallbackToPage("/_Host"); app.MapFallbackToPage("/_Host");

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Title" xml:space="preserve">
<value>Liste des éléments</value>
</data>
</root>

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Title" xml:space="preserve">
<value>Items List</value>
</data>
</root>

@ -0,0 +1,43 @@
@using System.Globalization
@inject NavigationManager NavigationManager
<p>
<label>
Select your locale:
<select @bind="Culture">
@foreach (var culture in supportedCultures)
{
<option value="@culture">@culture.DisplayName</option>
}
</select>
</label>
</p>
@code
{
private CultureInfo[] supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("fr-FR")
};
private CultureInfo Culture
{
get => CultureInfo.CurrentCulture;
set
{
if (CultureInfo.CurrentUICulture == value)
{
return;
}
var culture = value.Name.ToLower(CultureInfo.InvariantCulture);
var uri = new Uri(this.NavigationManager.Uri).GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
var query = $"?culture={Uri.EscapeDataString(culture)}&" + $"redirectUri={Uri.EscapeDataString(uri)}";
// Redirect the user to the culture controller to set the cookie
this.NavigationManager.NavigateTo("/Culture/SetCulture" + query, forceLoad: true);
}
}
}

@ -10,6 +10,9 @@
<main> <main>
<div class="top-row px-4"> <div class="top-row px-4">
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a> <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
<div class="px-4">
<CultureSelector />
</div>
</div> </div>
<article class="content px-4"> <article class="content px-4">

@ -0,0 +1,28 @@
@typeparam TItem
@using System.Diagnostics.CodeAnalysis
<table class="table">
<thead>
<tr>@TableHeader</tr>
</thead>
<tbody>
@foreach (var item in Items)
{
if (RowTemplate is not null)
{
<tr>@RowTemplate(item)</tr>
}
}
</tbody>
</table>
@code {
[Parameter]
public RenderFragment? TableHeader { get; set; }
[Parameter]
public RenderFragment<TItem>? RowTemplate { get; set; }
[Parameter, AllowNull]
public IReadOnlyList<TItem> Items { get; set; }
}

@ -19,6 +19,18 @@ build_property._RazorSourceGeneratorDebug =
build_metadata.AdditionalFiles.TargetPath = QXBwLnJhem9y build_metadata.AdditionalFiles.TargetPath = QXBwLnJhem9y
build_metadata.AdditionalFiles.CssScope = build_metadata.AdditionalFiles.CssScope =
[C:/Users/felix/Documents/BUT2/Blazor/TP/Sources/BlazorApp/BlazorApp/Components/Card.razor]
build_metadata.AdditionalFiles.TargetPath = Q29tcG9uZW50c1xDYXJkLnJhem9y
build_metadata.AdditionalFiles.CssScope =
[C:/Users/felix/Documents/BUT2/Blazor/TP/Sources/BlazorApp/BlazorApp/Components/ShowItems.razor]
build_metadata.AdditionalFiles.TargetPath = Q29tcG9uZW50c1xTaG93SXRlbXMucmF6b3I=
build_metadata.AdditionalFiles.CssScope =
[C:/Users/felix/Documents/BUT2/Blazor/TP/Sources/BlazorApp/BlazorApp/Components/TestRenderFragment.razor]
build_metadata.AdditionalFiles.TargetPath = Q29tcG9uZW50c1xUZXN0UmVuZGVyRnJhZ21lbnQucmF6b3I=
build_metadata.AdditionalFiles.CssScope =
[C:/Users/felix/Documents/BUT2/Blazor/TP/Sources/BlazorApp/BlazorApp/Modals/DeleteConfirmation.razor] [C:/Users/felix/Documents/BUT2/Blazor/TP/Sources/BlazorApp/BlazorApp/Modals/DeleteConfirmation.razor]
build_metadata.AdditionalFiles.TargetPath = TW9kYWxzXERlbGV0ZUNvbmZpcm1hdGlvbi5yYXpvcg== build_metadata.AdditionalFiles.TargetPath = TW9kYWxzXERlbGV0ZUNvbmZpcm1hdGlvbi5yYXpvcg==
build_metadata.AdditionalFiles.CssScope = build_metadata.AdditionalFiles.CssScope =
@ -55,6 +67,26 @@ build_metadata.AdditionalFiles.CssScope =
build_metadata.AdditionalFiles.TargetPath = UGFnZXNcTGlzdC5yYXpvcg== build_metadata.AdditionalFiles.TargetPath = UGFnZXNcTGlzdC5yYXpvcg==
build_metadata.AdditionalFiles.CssScope = build_metadata.AdditionalFiles.CssScope =
[C:/Users/felix/Documents/BUT2/Blazor/TP/Sources/BlazorApp/BlazorApp/Pages/Pets1.razor]
build_metadata.AdditionalFiles.TargetPath = UGFnZXNcUGV0czEucmF6b3I=
build_metadata.AdditionalFiles.CssScope =
[C:/Users/felix/Documents/BUT2/Blazor/TP/Sources/BlazorApp/BlazorApp/Pages/Pets2.razor]
build_metadata.AdditionalFiles.TargetPath = UGFnZXNcUGV0czIucmF6b3I=
build_metadata.AdditionalFiles.CssScope =
[C:/Users/felix/Documents/BUT2/Blazor/TP/Sources/BlazorApp/BlazorApp/Pages/Pets3.razor]
build_metadata.AdditionalFiles.TargetPath = UGFnZXNcUGV0czMucmF6b3I=
build_metadata.AdditionalFiles.CssScope =
[C:/Users/felix/Documents/BUT2/Blazor/TP/Sources/BlazorApp/BlazorApp/Pages/Pets4.razor]
build_metadata.AdditionalFiles.TargetPath = UGFnZXNcUGV0czQucmF6b3I=
build_metadata.AdditionalFiles.CssScope =
[C:/Users/felix/Documents/BUT2/Blazor/TP/Sources/BlazorApp/BlazorApp/Shared/CultureSelector.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXEN1bHR1cmVTZWxlY3Rvci5yYXpvcg==
build_metadata.AdditionalFiles.CssScope =
[C:/Users/felix/Documents/BUT2/Blazor/TP/Sources/BlazorApp/BlazorApp/Shared/DoctorWhoLayout.razor] [C:/Users/felix/Documents/BUT2/Blazor/TP/Sources/BlazorApp/BlazorApp/Shared/DoctorWhoLayout.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXERvY3Rvcldob0xheW91dC5yYXpvcg== build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXERvY3Rvcldob0xheW91dC5yYXpvcg==
build_metadata.AdditionalFiles.CssScope = build_metadata.AdditionalFiles.CssScope =
@ -63,10 +95,22 @@ build_metadata.AdditionalFiles.CssScope =
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXFN1cnZleVByb21wdC5yYXpvcg== build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXFN1cnZleVByb21wdC5yYXpvcg==
build_metadata.AdditionalFiles.CssScope = build_metadata.AdditionalFiles.CssScope =
[C:/Users/felix/Documents/BUT2/Blazor/TP/Sources/BlazorApp/BlazorApp/Shared/TableTemplate.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXFRhYmxlVGVtcGxhdGUucmF6b3I=
build_metadata.AdditionalFiles.CssScope =
[C:/Users/felix/Documents/BUT2/Blazor/TP/Sources/BlazorApp/BlazorApp/_Imports.razor] [C:/Users/felix/Documents/BUT2/Blazor/TP/Sources/BlazorApp/BlazorApp/_Imports.razor]
build_metadata.AdditionalFiles.TargetPath = X0ltcG9ydHMucmF6b3I= build_metadata.AdditionalFiles.TargetPath = X0ltcG9ydHMucmF6b3I=
build_metadata.AdditionalFiles.CssScope = build_metadata.AdditionalFiles.CssScope =
[C:/Users/felix/Documents/BUT2/Blazor/TP/Sources/BlazorApp/BlazorApp/Components/Crafting.razor]
build_metadata.AdditionalFiles.TargetPath = Q29tcG9uZW50c1xDcmFmdGluZy5yYXpvcg==
build_metadata.AdditionalFiles.CssScope = b-0c7vkjpwvp
[C:/Users/felix/Documents/BUT2/Blazor/TP/Sources/BlazorApp/BlazorApp/Components/CraftingItem.razor]
build_metadata.AdditionalFiles.TargetPath = Q29tcG9uZW50c1xDcmFmdGluZ0l0ZW0ucmF6b3I=
build_metadata.AdditionalFiles.CssScope = b-syyk20fth2
[C:/Users/felix/Documents/BUT2/Blazor/TP/Sources/BlazorApp/BlazorApp/Shared/MainLayout.razor] [C:/Users/felix/Documents/BUT2/Blazor/TP/Sources/BlazorApp/BlazorApp/Shared/MainLayout.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXE1haW5MYXlvdXQucmF6b3I= build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXE1haW5MYXlvdXQucmF6b3I=
build_metadata.AdditionalFiles.CssScope = b-3dsd3z3yec build_metadata.AdditionalFiles.CssScope = b-3dsd3z3yec

Loading…
Cancel
Save