L'Object Tree (chiamato anche Visual Tree) è la rappresentazione concettuale dell'interfaccia grafica, la quale è composta da una serie di elementi che possono avere a sua volta uno o più oggetti figlio relazionati fra loro, il risultato è una rappresentazione ad albero. Silverlight permette l'accesso all'Object Tree sia tramite codice JavaScript, sia tramite code-behind.
Tuttavia, la rappresentazione non è composta da proprio tutti gli elementi dell'interfaccia utente: vengono esposti solo gli oggetti che partecipano alla fase di renderizazzione. Anche gli elementi creati e aggiunti dinamicamente via codice procedurale possono interessare l'Object Tree.
Silverlight 2 mette a disposizioni una classe di supporto, VisualTreeHelper (contenuta nel namespace System.Windows.Media), per accedere alla struttura ad albero.
Vediamo un esempio di utilizzo: creiamo un'interfaccia composta da un serie di elementi, alcuni dei quali aggiunti da codice procedurale. Cominciamo scrivendo il seguente XAML:
<StackPanel x:Name="LayoutRoot"
Width="300"
VerticalAlignment="Center" HorizontalAlignment="Center"
Background="Blue">
<TextBlock Margin="10" Foreground="White" FontSize="28"
Text="Contatti" />
<ListBox x:Name="Contacts">
<ListBoxItem Content="Mario Rossi" />
<ListBoxItem Content="Matteo Baglini" />
</ListBox>
</StackPanel>
Per creare l'interfaccia usiamo come elemento base uno StackPanel con sfondo di colore blu, composto da un "header" e da una lista di contatti fittizi. Procediamo aggiungendo due metodi nel code-behind per creare una parte di interfaccia via codice, composta da uno StackPanel contenente due controlli Button:
private UIElement CreateChild()
{
StackPanel panel = new StackPanel();
panel.Orientation = Orientation.Horizontal;
panel.HorizontalAlignment = HorizontalAlignment.Right;
Button okButton = CreateButton("Conferma");
Button cancelButton = CreateButton("Annulla");
panel.Children.Add(okButton);
panel.Children.Add(cancelButton);
return panel;
}
private Button CreateButton(string text)
{
Button button = new Button();
button.Content = text;
button.Margin = new Thickness(5);
button.Height = 25;
button.Width = 80;
return button;
}
Per finire, nel costruttore dello UserControl, richiamiamo il metodo CreateChild ed aggiungiamo il valore restituito alla collezione di oggetti figlio del controllo primario LayoutRoot:
public Page()
{
InitializeComponent();
LayoutRoot.Children.Add(CreateChild());
}
Per visualizzare l'Object Tree tramite la classe VisualTreeHelper inseriamo nel code-behind un metodo che sarà invocato in maniera ricorsiva e che ci permetterà di percorrere l'albero dei componenti dall'alto verso il basso e stamperà nella console di output del debugger di Visual Studio tutti gli elementi trovati:
private void PrintVisualTree(int depth, DependencyObject obj)
{
Debug.WriteLine(new string(' ', depth) + obj);
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
PrintVisualTree(depth + 1, VisualTreeHelper.GetChild(obj, i));
}
La chiamata a questo metodo sarà impostata nel gestore dell'evento Load dello UserControl, il quale andrà agganciato nel costruttore della classe:
public Page()
{
InitializeComponent();
LayoutRoot.Children.Add(CreateChild());
Loaded += new RoutedEventHandler(Page_Loaded);
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
PrintVisualTree(0, this);
}
Eseguendo l'applicazione con il debugger attivo il risultato sarà il seguente:
Il log mostrato ci permette di capire la macro struttura dello UserControl primario Page.
Se vuoi aggiornamenti su .NET inserisci la tua email nel box qui sotto: