VEFramework.VEBlazor.Editable
0.4.2
dotnet add package VEFramework.VEBlazor.Editable --version 0.4.2
NuGet\Install-Package VEFramework.VEBlazor.Editable -Version 0.4.2
<PackageReference Include="VEFramework.VEBlazor.Editable" Version="0.4.2" />
paket add VEFramework.VEBlazor.Editable --version 0.4.2
#r "nuget: VEFramework.VEBlazor.Editable, 0.4.2"
// Install VEFramework.VEBlazor.Editable as a Cake Addin #addin nuget:?package=VEFramework.VEBlazor.Editable&version=0.4.2 // Install VEFramework.VEBlazor.Editable as a Cake Tool #tool nuget:?package=VEFramework.VEBlazor.Editable&version=0.4.2
VEBlazor.Editable
Komponenta Editable
je dodatečným (extension) balíčkem VEBlazor
knihovny. Vznikla kvůli potřebě častého zobrazování parametrů tříd v UI a jejich editace.
C# v kódu umožňuje pracovat s abstraktní vrstvou tříd. Příkladem využití v praxi je komponenta Editable
resp. její vnitřní logika. Příklad demonstrace komponenty na projektu VEBlazor.Editable.Demo.
Demo vychází ze standardního dema pro Blazor WASM aplikaci. Navíc je přidána reference na projekt/balíček VEFramework.VEBlazor.Editable
. Definice modelu třídy Piano
, komponenta Piano
a její přidání do Index.razor
. Definice třídy obsahuje několik základních parametrů piána:
namespace VEBlazor.Editable.Demo.Models
{
public class Piano
{
public string Name { get; set; } = string.Empty;
public string Brand { get; set; } = string.Empty;
public int NumberOfKeys { get; set; } = 88;
public double Volume { get; set; } = 0.5;
public bool IsOn { get; set; } = true;
}
}
Parametry jsou různých typů. Pro jejich zobrazení a editaci, by byla potřeba samostatná logika. A tu řeší právě komponenta Editable
. Pokud je potřeba zobrazit parametr a umožnit jeho editaci, lze to udělat tak jako v komponentě PianoComponent.razor
<Editable Item="@PianoModel" ParameterName="@(nameof(PianoModel.Name))" TItem="Piano" ItemChanged="@OnPianoChanged" />
<Editable Item="@PianoModel" ParameterName="@(nameof(PianoModel.Brand))" TItem="Piano" ItemChanged="@OnPianoChanged" />
<Editable Item="@PianoModel" ParameterName="@(nameof(PianoModel.NumberOfKeys))" TItem="Piano" ItemChanged="@OnPianoChanged" />
<Editable Item="@PianoModel" ParameterName="@(nameof(PianoModel.Volume))" TItem="Piano" ItemChanged="@OnPianoChanged" />
<Editable Item="@PianoModel" ParameterName="@(nameof(PianoModel.IsOn))" TItem="Piano" ItemChanged="@OnPianoChanged" />
Pro všechny parametry je společný handler pro detekci jejich změny - OnPianoChanged
, který propaguje i aktualizovanou verzi objektu:
[Parameter]
public Piano PianoModel { get; set; } = new Piano() { Name = "S82", Brand = "Yamaha" };
private void OnPianoChanged(Piano e)
{
PianoModel = e;
StateHasChanged();
}
Blazor umožňuje definovat, že komponenta bude přebírat generický typ objektu. To se provede tak, že se na začátek .razor
souboru napíše:
@typeparam TItem
Tím se definuje TItem
jako Parametr
, ideálně s OnChanged
EventCallbackem, aby se s objektem dalo v kódu pracovat.
[Parameter]
public TItem? Item { get; set; }
[Parameter]
public EventCallback<TItem> ItemChanged { get; set; }
Aby komponenta věděla, se kterým parametrem v objektu má pracovat (jestli s Name
, Volume
, apod.) je potřeba zadat název parametru:
[Parameter]
public string? ParameterName { get; set; }
Ten je zadaný jako string, nicméně se doporučuje volbu parametru nezadávat natvrdo. Spíš se doporučuje využít konstrukci s nameof
, protože pokud se automaticky přes IDE mění název ve třídě, správně se zpropaguje/změní všude. Příklad:
nameof(PianoModel.Name) // takto namísto "Name"
C# dokáže identifikovat názvy proměných a funkcí ve třídě. Ty pak vyhledat a přistupovat k nim jako k objektům. Díky tomu lze zjistit typ a přizpůsobit čtení/editaci hodnoty. To samé platí pro zobrazení v UI. Dohledání typu lze udělat automaticky, což je řešeno funkcí LoadParam.
Na začátku se ověří, jestli v objektu typu TItem
existuje konkrétní jméno parametru. Pokud ano, vrátí první parametr jména, pokud ne, vrátí null
.
var param = typeof(TItem).GetProperties().Where(p => p.Name == ParameterName).FirstOrDefault();
Pokud je možné parametr číst, získá se jeho hodnota a podle typu se převede do obecné proměné ParametrValue
:
if (param != null && param.CanRead)
{
var value = param.GetValue(Item);
if (value != null)
{
paramType = param.PropertyType;
if (param.PropertyType == typeof(string) || param.PropertyType == typeof(String))
ParameterValue = (string)value;
else if (param.PropertyType == typeof(int))
ParameterValue = (int)value;
else if (param.PropertyType == typeof(double))
ParameterValue = (double)value;
else if (param.PropertyType == typeof(bool))
ParameterValue = (bool)value;
await InvokeAsync(StateHasChanged);
}
}
Za zmínku ještě stojí funkce, která zajistí uložení parametru:
private async Task Save()
{
Editing = false;
var param = typeof(TItem).GetProperties().Where(p => p.Name == ParameterName).FirstOrDefault();
if (param != null && param.CanWrite)
{
param.SetValue(Item, ParameterValue);
await ItemChanged.InvokeAsync(Item);
}
await InvokeAsync(StateHasChanged);
}
Při ukládání se opět zavolá parametr jako obecný objekt a pomocí jeho funkce SetValue
se mu přiřadí nová hodnota. Musí se ale zajistit správnost zadané hodnoty. To řeší funkce OnValueChanged, která parsuje vstup od uživatele podle identifikovaného typu parametru, který se dohledal automaticky:
paramType = param.PropertyType;
Komponentu by bylo vhodné rozšířit ještě minimálně o datum. Případné další návrhy a dokonce kontribuce jsou vítány 😃
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net6.0
- Microsoft.AspNetCore.Components.Web (>= 6.0.21)
-
net7.0
- Microsoft.AspNetCore.Components.Web (>= 7.0.11)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on VEFramework.VEBlazor.Editable:
Package | Downloads |
---|---|
VEFramework.VEBlazor.EntitiesBlocks
Blazor Component library for .NET drivers for calculation of the entities and its time based blocks with specfic amount. |
GitHub repositories
This package is not used by any popular GitHub repositories.