Questa mi sembra una cosa abbastanza semplice da implementare, se si progetta il tuo modello di vista in modo corretto.
Fondamentalmente si progettano gli elementi nello stesso modo in cui si visualizzeranno in una normale griglia di dati, vale a dire che ogni articolo ha una proprietà per ogni colonna. Con ogni probabilità, il modello di dati sottostante è gerarchico, ma la raccolta alla quale la griglia è vincolata verrà appiattita, cioè conterrà un elemento per ciascun nodo nella gerarchia, indipendentemente dalle relazioni padre/figlio.
L'articolo vista del modello ha alcune proprietà aggiuntive: Level
, Children
, IsExpanded
e IsVisible
. Level
è un conteggio degli antenati del nodo, Children
contiene i nodi del modello di visualizzazione figlio, IsExpanded
viene utilizzato nell'interfaccia utente e IsVisible
è true se il nodo è visibile. Implementa anche una proprietà chiamata VisibleDescendants
:
public IEnumerable<NodeViewModel> VisibleDescendants
{
get
{
return Children
.Where(x => x.IsVisible)
.SelectMany(x => (new[] {x}).Concat(x.VisibleDescendants)));
}
}
Si utilizza Level
, HasChildren
, e IsExpanded
nello stile per la voce nella prima colonna del controllo: essi controllano il margine sinistro e che tipo di icona (se presente) è visualizzato.
È inoltre necessario implementare le proprietà ExpandCommand
e CollapseCommand
. Il ExpandCommand
è abilitato se Children.Any()
è vero e IsExpanded
è falso e CollapseCommand
è abilitato se Children.Any()
è vero e IsExpanded
è vero. Questi comandi, una volta eseguiti, modificano il valore di IsExpanded
.
Ed ecco dove diventa interessante. Il modo semplice per implementare questo può funzionare per te: gli oggetti sono esposti da un modello di visualizzazione genitore la cui proprietà Items
non è una collezione. Invece, è un enumeratore che viaggia lungo la catena di vista figlio modelli e produce solo i nodi visibili:
public IEnumerable<NodeViewModel> Items
{
get
{
return _Items
.Where(x => x.IsVisible)
.SelectMany(x => (new[] {x}).Concat(x.VisibleDescendants));
}
}
Ogni volta IsVisible
modifiche alle proprietà di qualsiasi discendenti, la vista del modello genitore solleva PropertyChanged
per la proprietà Items
, che costringe i dati griglia da ripopolare.
C'è un meno semplice implementazione troppo, in cui si effettua la Items
proprietà una classe che implementa INotifyCollectionChanged
, e che solleva la corretta CollectionChanged
eventi quando nodi discendenti diventano visibili/invisibili, ma si vuole solo andare lì se le prestazioni sono un problema .
Ma io voglio ibridarlo con un DataGrid (modificabile) – Shimmy
+1 @Shimmy Vedi com parte di http://www.codeproject.com/KB/WPF/wpf_treelistview_control.aspx. mostra come usarlo con una griglia invece di una listview – k3b
@ k3b dovresti aver diretto questo @Hedge. Penso che questo non sia davvero un problema a cui @Shimmy si preoccupa più ... semplicemente dicendo ... –