dies wie eine ziemlich einfache Sache, mir scheint, zu implementieren, wenn Sie richtig Ihre Ansicht Modell entwerfen.
Sie entwerfen die Elemente grundsätzlich so, als würden Sie sie in einem normalen Datenraster anzeigen, d. H. Jedes Element verfügt über eine Eigenschaft für jede Spalte. Das zugrundeliegende Datenmodell ist aller Wahrscheinlichkeit nach hierarchisch, aber die Sammlung, an die das Raster gebunden ist, wird abgeflacht, d. H. Es enthält ein Element für jeden Knoten in der Hierarchie, unabhängig von Eltern/Kind-Beziehungen.
Der Artikel View-Modell hat einige zusätzliche Eigenschaften: Level
, Children
, IsExpanded
und IsVisible
. Level
ist eine Anzahl der Vorfahren des Knotens, Children
enthält die untergeordneten Ansichtsmodellknoten, IsExpanded
wird in der Benutzeroberfläche verwendet, und IsVisible
ist wahr, wenn der Knoten sichtbar ist. Es implementiert eine Eigenschaft namens VisibleDescendants
:
public IEnumerable<NodeViewModel> VisibleDescendants
{
get
{
return Children
.Where(x => x.IsVisible)
.SelectMany(x => (new[] {x}).Concat(x.VisibleDescendants)));
}
}
Sie Level
verwenden, HasChildren
und IsExpanded
im Stil für das Element in der ersten Spalte der Kontrolle: Sie steuern den linken Rand und welche Art von Symbol (falls vorhanden) ist angezeigt.
Sie müssen auch die Eigenschaften ExpandCommand
und CollapseCommand
implementieren. Die ExpandCommand
ist aktiviert, wenn Children.Any()
ist wahr und IsExpanded
ist falsch, und die CollapseCommand
ist aktiviert, wenn Children.Any()
ist wahr und IsExpanded
ist wahr. Diese Befehle ändern bei ihrer Ausführung den Wert IsExpanded
.
Und hier wird es interessant. Die einfache Möglichkeit, dies zu implementieren, funktioniert möglicherweise für Sie: Die Elemente werden von einem übergeordneten Ansichtsmodell bereitgestellt, dessen Items
-Eigenschaft keine Sammlung ist. Stattdessen ist es ein Enumerator, die Kette der untergeordneten Ansicht Modelle reist nach unten und liefert nur den sichtbaren Knoten:
public IEnumerable<NodeViewModel> Items
{
get
{
return _Items
.Where(x => x.IsVisible)
.SelectMany(x => (new[] {x}).Concat(x.VisibleDescendants));
}
}
Wann immer einen IsVisible
Eigenschaftsänderungen des Nachkommen, das übergeordnete Ansicht Modell wirft PropertyChanged
für die Items
Eigenschaft, die die Daten zwingt Raster neu zu bevölkern.
Es gibt eine weniger einfache Implementierung zu, wo Sie die Items
Eigenschaft eine Klasse machen, die INotifyCollectionChanged
implementiert, und das wirft die richtigen CollectionChanged
Ereignisse, wenn absteigende Knoten sichtbar/unsichtbar, aber Sie wollen nur dorthin gehen, wenn die Leistung ist ein Problem .
Aber ich möchte es mit einem DataGrid (editierbar) – Shimmy
+1 @Shimmy See com Hybrid Teil von http://www.codeproject.com/KB/WPF/wpf_treelistview_control.aspx. es zeigt, wie man es mit einem Raster statt einer Listenansicht verwendet – k3b
@ k3b sollten Sie diese @Hedge gerichtet haben. Ich denke, das ist nicht wirklich ein Problem @ Shimmy kümmert sich nicht mehr um ... nur zu sagen ... –