This article is currently in the process of being translated into Italian (~96% done).
TreeView, associazione dati e modelli multipli
TreeView WPF supporta l'associazione dei dati, come praticamente tutti gli altri controlli WPF, ma poiché TreeView è di natura gerarchica, un DataTemplate normale non è spesso sufficiente. Al contrario, utilizziamo HierarchicalDataTemplate, che ci consente di modellare sia il nodo dell'albero stesso, controllando al contempo quale proprietà utilizzare come origine per gli elementi figlio del nodo.
Un TreeView basato su una associazione dati
Nel seguente esempio, ti mostrerò quanto è facile utilizzare un HierarchicalDataTemplate:
<Window x:Class="WpfTutorialSamples.TreeView_control.TreeViewDataBindingSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:self="clr-namespace:WpfTutorialSamples.TreeView_control"
Title="TreeViewDataBindingSample" Height="150" Width="200">
<Grid Margin="10">
<TreeView Name="trvMenu">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type self:MenuItem}" ItemsSource="{Binding Items}">
<TextBlock Text="{Binding Title}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Windows;
using System.IO;
using System.Collections.ObjectModel;
namespace WpfTutorialSamples.TreeView_control
{
public partial class TreeViewDataBindingSample : Window
{
public TreeViewDataBindingSample()
{
InitializeComponent();
MenuItem root = new MenuItem() { Title = "Menu" };
MenuItem childItem1 = new MenuItem() { Title = "Child item #1" };
childItem1.Items.Add(new MenuItem() { Title = "Child item #1.1" });
childItem1.Items.Add(new MenuItem() { Title = "Child item #1.2" });
root.Items.Add(childItem1);
root.Items.Add(new MenuItem() { Title = "Child item #2" });
trvMenu.Items.Add(root);
}
}
public class MenuItem
{
public MenuItem()
{
this.Items = new ObservableCollection<MenuItem>();
}
public string Title { get; set; }
public ObservableCollection<MenuItem> Items { get; set; }
}
}
Nel markup XAML, ho specificato un HierarchicalDataTemplate come ItemTemplate del TreeView. Specifico di utilizzare la proprietà Items per trovare gli elementi figlio, impostando la proprietà ItemsSource del modello e al suo interno definisco il modello reale, che per ora consiste solo in un blocco di testo associato alla proprietà Title.
Questo primo esempio è stato molto semplice, in effetti così semplice che avremmo anche potuto semplicemente aggiungere manualmente gli elementi TreeView, invece di generare un insieme di oggetti e quindi vincolarli. Tuttavia, non appena le cose diventano un po' più complicate, i vantaggi dell'utilizzo delle associazioni dei dati diventano più evidenti.
Più modelli per tipi differenti
Il prossimo esempio è un caso leggermente più complesso in cui viene mostrato un albero di famiglie e dei loro membri. Una famiglia dovrebbe essere rappresentata in un modo, mentre ciascuno dei suoi membri dovrebbe essere mostrato in un altro modo. Si riesce a fare questo creando due modelli diversi e specificandoli come risorse dell'albero (o della finestra o dell'applicazione - dipende da te), e quindi consentendo a TreeView di scegliere il modello corretto in base al tipo di dati sottostante.
Ecco il codice, la spiegazione seguirà subito dopo:
<Window x:Class="WpfTutorialSamples.TreeView_control.TreeViewMultipleTemplatesSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:self="clr-namespace:WpfTutorialSamples.TreeView_control"
Title="TreeViewMultipleTemplatesSample" Height="200" Width="250">
<Grid Margin="10">
<TreeView Name="trvFamilies">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type self:Family}" ItemsSource="{Binding Members}">
<StackPanel Orientation="Horizontal">
<Image Source="/WpfTutorialSamples;component/Images/group.png" Margin="0,0,5,0" />
<TextBlock Text="{Binding Name}" />
<TextBlock Text=" [" Foreground="Blue" />
<TextBlock Text="{Binding Members.Count}" Foreground="Blue" />
<TextBlock Text="]" Foreground="Blue" />
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type self:FamilyMember}">
<StackPanel Orientation="Horizontal">
<Image Source="/WpfTutorialSamples;component/Images/user.png" Margin="0,0,5,0" />
<TextBlock Text="{Binding Name}" />
<TextBlock Text=" (" Foreground="Green" />
<TextBlock Text="{Binding Age}" Foreground="Green" />
<TextBlock Text=" years)" Foreground="Green" />
</StackPanel>
</DataTemplate>
</TreeView.Resources>
</TreeView>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Windows;
using System.Collections.ObjectModel;
namespace WpfTutorialSamples.TreeView_control
{
public partial class TreeViewMultipleTemplatesSample : Window
{
public TreeViewMultipleTemplatesSample()
{
InitializeComponent();
List<Family> families = new List<Family>();
Family family1 = new Family() { Name = "The Doe's" };
family1.Members.Add(new FamilyMember() { Name = "John Doe", Age = 42 });
family1.Members.Add(new FamilyMember() { Name = "Jane Doe", Age = 39 });
family1.Members.Add(new FamilyMember() { Name = "Sammy Doe", Age = 13 });
families.Add(family1);
Family family2 = new Family() { Name = "The Moe's" };
family2.Members.Add(new FamilyMember() { Name = "Mark Moe", Age = 31 });
family2.Members.Add(new FamilyMember() { Name = "Norma Moe", Age = 28 });
families.Add(family2);
trvFamilies.ItemsSource = families;
}
}
public class Family
{
public Family()
{
this.Members = new ObservableCollection<FamilyMember>();
}
public string Name { get; set; }
public ObservableCollection<FamilyMember> Members { get; set; }
}
public class FamilyMember
{
public string Name { get; set; }
public int Age { get; set; }
}
}
Come accennato, i due modelli sono dichiarati come parte delle risorse TreeView, consentendo a TreeView di selezionare il modello appropriato in base al tipo di dati che sta per mostrare. Il modello definito per il tipo Family è un modello gerarchico, utilizzando la proprietà Members per mostrare i membri della sua famiglia.
Il modello definito per il tipo FamilyMember è un normale DataTemplate, poiché questo tipo non ha membri figlio. Tuttavia, se noi avessimo voluto che ogni FamilyMember tenesse una raccolta dei loro figli e dei figli dei loro figli, avremmo usato un modello gerarchico.
In entrambi i modelli, utilizziamo un'immagine che rappresenta una famiglia o un membro della famiglia, quindi mostriamo anche alcuni dati interessanti al riguardo, come la quantità di membri della famiglia o l'età della persona.
Nel code-behind, creiamo semplicemente due istanze Family, riempiamo ognuna di esse con un set di membri, quindi aggiungiamo ciascuna delle famiglie a un elenco, che viene quindi utilizzato come origine degli elementi per TreeView.
Riassunto
Utilizzando l'associazione dei dati, TreeView è molto personalizzabile ed è possibile specificare più modelli per il rendering di diversi tipi di dati.