DropDownList Control mit Blazor- so wie es Telerik machen würde

Der trockene Hitzesommer, wie er noch im März quer durch die Tageszeitungen angekündigt wurde, hat heute wieder voll zugeschlagen. Regen 16°. So oft wie dieses Jahr hatte ich jedenfalls noch nie Sitzheizung an. Es gilt Beschäftigungsprogramm.

So schmökere ich ein wenig in der Telerik Doku zu den Blazor Radcontrols. Wahllos eine Sample aus der Website genommen und in ein Visual Studio Blazor Solution kopiert. Mit geringfügigen Änderungen, die grad nichts zur Sache tun.

   1:  <DropDownList Data="@myDdlData" TextField="MyTextField" ValueField="MyValueField"
ItemType="MyDdlModel"
   2:                       @bind-Value="@DdlValue" DefaultText="Select something">
   3:  </DropDownList>
   4:  @DdlValue
   5:  @code {
   6:      public string DdlValue;
   7:      IEnumerable<MyDdlModel> myDdlData = Enumerable.Range(1, 20).Select(x => 
new MyDdlModel { MyTextField = "Eintrag " + x, MyValueField = x });
   8:      
   9:      public class MyDdlModel
  10:      {
  11:          public int MyValueField { get; set; }
  12:          public string MyTextField { get; set; }
  13:      }
  14:  }

Die kleine Wochenend Kreuzworträtsel Ersatz Tätigkeit. Baue die Component dazu. Zunächst der HTML Teil in der .razor Datei. Mit dem TypeParam erlaubt es Microsoft einen Typ als Parameter zu übergeben und so generische Komponenten zu bauen, die mit beliebigen Datentypen zurecht kommen. Damit lässt sich eine generische Liste einer Komponente überreichen. Der Code ist noch nicht fertig. Es fehlt unter anderem wie wir in diesem Fall mit den generischen Feldern umgehen um dann Item.Feld binden zu können.

   1:  @typeparam ItemType
   2:   <select>
   3:     @foreach (var Item in Data)
   4:      {
   5:        <option value="@Item">@Item</option>
   6:   }
   7:  </select>

Blazor typisch werden Propertys mit dem Parameter Attribut deklariert um diese im Razor Taghelper auch mit Werten belegen zu können. Kann man ganz gut im ersten HTML Code Part erkennen.

Besonderheit ist die generische Liste mit einem generischen ItemType. Der Typ wird wiederum im obigen HTML Sample auf die Model Klasse der Listenelement gesetzt. (Itemtype=…)

   1:  [Parameter]
   2:  public IEnumerable<ItemType> Data { get; set; }
   3:  [Parameter]
   4:  public string TextField { get; set; }
   5:  [Parameter]
   6:  public string ValueField { get; set; }
   7:  [Parameter]
   8:  public string DefaultText { get; set; }

Jetzt kommt noch ein pikantes interal von Blazor. Wie klapptz das mit @bind-value? Für 2-Wege Binding wird immer @bind genutzt um die Eigenschaft des Objektes zuzuweisen.  Wenn man gezielt eine Eigenschaft des UI Elements mit einer Eigenschaft des Objektes verweben möchte, nutzt man @bind-. Der Wert hinter dem Minus gibt den Namen des Propertys aus der Komponente an. Zugegebenermaßen- ein wenig Magie.

In unserem Fall braucht ein @bind-value also ein Property mit dem Namen Value in der DropDownList Komponente. Allerdings muss der Wert auch zurück geschrieben werden und dafür will Microsoft ein EventCallback. Konvention Name des Propertys+ Changed und als Rückgabetyp der Typ des gebundenen Value – also hier String.

   1:  [Parameter]
   2:  public string Value { get; set; }
   3:  [Parameter]
   4:  public EventCallback<string> ValueChanged { get; set; }

 

Telerik hat sich entschieden die Felder für angezeigten Wert und gebunden Wert als Text zu übergeben. Damit scheidet ein direktes @bind=”Text” aus. Wir brauchen Reflection um das aufzulösen. Das generische Item wird so in seine echten Felder bzw Feldwerte zerlegt.

   1:  private string ItemValue(ItemType Item)
   2:    {
   3:       return Item.GetType()
   4:        .GetProperty(ValueField)
   5:        .GetValue(Item, null)
   6:        .ToString();
   7:   }
   8:  private string ItemText(ItemType Item)
   9:   {
  10:     return Item.GetType()
  11:       .GetProperty(TextField)
  12:       .GetValue(Item, null)
  13:      .ToString();
  14:  }

Auf die Art und weise kann man dann auch das Binding definieren. Ergänzt wird noch das Event, das letztendlich die Zuweisung des durch den Benutzer gewählten Eintrages (Magie!) ausführt.

Das allererste HTMl Schnipsel aus diesem Blazor Blog Post wird also geändert wie folgt

   1:   <select   @onchange="(_) => 
ValueChanged.InvokeAsync(_.Value.ToString())">
   2:     @foreach (var Item in Data)
   3:     {
   4:      <option value="@ItemValue(Item)">@ItemText(Item)</option>
   5:     }
   6:   </select>

Dies ist eines meiner Beispiele aus dem ppedv Blazor Kurs. Findet man auch auf Github.

Kommentare sind geschlossen