head.WriteLine()

Mittwoch, März 17, 2010

TT.DOM: Views, Teil 2

Wie im ersten Teil bereits beschrieben, bietet TT.DOM ein View-Modell, das es ermöglicht beliebig viele Sichten auf eine Liste zu erzeugen. Während es zuletzt um die Möglichkeiten ging, Sortier- und Filterkriterien auf die View anzuwenden, möchte ich in diesem Post beschreiben, wie Sie die Darstellung einer View anpassen und um berechnete Spalten erweitern können.

Views anpassen

Wie hier bereit beschrieben, basiert die Anpassbarkeit der Views auf dem Interface ITypedList. Es definiert die GetItemProperties()-Methode, über die das gebundene Listensteuerelement Informationen über die Spalten der Datenquelle abfragt. Sie gibt eine Collection von PropertyDescriptor-Objekten zurück, welche die jeweiligen Eigenschaften beschreiben. Über einen PropertyDescriptor kann beispielsweise festgelegt werden, welchen Anzeigenamen eine Eigenschaft bei der Bindung annehmen soll, ob diese schreibgeschützt ist oder diese ausgeblendet werden soll. Diese Darstellungsmerkmale ermittelt die PropertyDescriptor-Klasse per Reflection aus der Datenklasse. In der Datenklasse können die Merkmale in Form von Attributen signalisiert werden:
[Browsable(false)]
public string Name { get; set; }

Hierbei können die folgenden Attribute aus dem Namespace System.ComponentModel verwendet werden:
  • Browsable bestimmt, ob die Eigenschaft angezeigt werden soll.
  • DisplayName gibt den Anzeigenamen an
  • ReadOnly steuert den Schreibschutz der Spalte
  • Description liefert eine Beschreibung der Spalte
Die folgende Abbildung zeigt die Kommunikation zwischen beteiligten Parteien:
ITypedList
Wie hier bereits erwähnt, haben Sie nicht immer Einfluss auf die Datenklasse, sodass Sie unter Umständen die genannten Attribute nicht setzen können. Hierfür bietet DataObjectView<T> die Eigenschaft ColumnAttributes. Sie enthält für jede Eigenschaft der Liste ein DisplayAttributeInfo-Objekt, über das die Darstellung gesteuert werden kann.
DataObjectView<Person> view = list.DefaultView;
view.ColumnAttributes["Id"].Browsable = false;
view.ColumnAttributes["FirstName"].DisplayName = "Vorname";
view.ColumnAttributes["LastName"].DisplayName = "Nachname";
view.ColumnAttributes["LastName"].ReadOnly = true;

Auf diese Weise können Sie die entsprechenden Anzeigeattribute programmatisch zuweisen, ohne die jeweilige Datenklasse anpassen zu müssen. Zudem kann es vorkommen, dass die Darstellung vom jeweiligen Kontext in der Anwendung abhängt.
Neben den genannten Anzeigeattributen bietet DisplayAttributeInfo über die Ordinal-Eigenschaft die Möglichkeit, die Position der Spalte für die Bindung festzulegen. Alternativ können Sie auch die SetOrdinal()-Methode der View verwenden.
list.DefaultView.SetOrdinal(
  "Id", "FirstName", "LastName");

Um diese Art der Anpassung auch dem Endanwender zu ermöglichen, bietet TT.DOM einen Standarddialog (CustomizeColumnsForm) mit dem die Darstellung zur Laufzeit angepasst werden kann.
CustomizeColumns

Berechnete Spalten

Über den ITypedList-Mechanismus stellt TT.DOM auch die Möglichkeit zu Verfügung, dynamisch berechnete Spalten zu definieren. Die Spalten werden hierbei über einen eigene PropertyDescriptor-Ableitung bereitgestellt, welche die Werte über einen Delegate ermitteln.
Die Anlage von berechneten Spalten erfolgt über die ComputedColumns-Eigenschaft von DataObjectView<T>. Hierbei geben Sie lediglich den Namen und den Typ der “virtuellen” Eigenschaft, sowie einen Delegate zur Berechnung an.
ComputedColumn col =
  new ComputedColumn("FullName", typeof(string),
    item =>
      ((Person)item).FirstName + " " +
      ((Person)item).LastName);
_persons.DefaultView.ComputedColumns.Add(col);

Daraufhin erscheint die Spalte automatisch im gebundenen Listensteuerelement. Das sich der Wert der Spalte automatisch aktualisiert, wenn sich die abhängigen Eigenschaften ändern, brauche ich wohl nicht zu erwähnen ;)
Auch bei dieser Technik besteht der Vorteil vor allem darin, berechnete Spalten bereitzustellen, ohne die zugrunde liegende Datenklasse anpassen zu müssen.

Labels: