sabato 28 giugno 2008

WPF TreeView

Mi è capitato più volte di leggere su altri Blog della problematica di sapere su quale elemento l'utente ha aperto il menu contestuale. C'è chi sostiene che in questi casi non si può usare il HierarchicalDataTemplate

<TreeViewItem Header="Categories" ItemsSource="{Binding Categories}" >
</TreeViewItem>
In pratica, uno dei miei TreeViewItem è "databindato" ad una gerarchia di categorie.
Da qualche altra parte (tra le risorse dell'applicativo) definisco un
HierarchicalDataTemplate per il tipo "Category":


<HierarchicalDataTemplate DataType="{x:Type my:Category}"
ItemsSource
="{Binding Path=Categories}" >
<TextBlock Text="{Binding Path=Name}" >
<TextBlock.ContextMenu>
<ContextMenu Name="MyMenu">
<MenuItem Header="New Category... "
Click
="NewCategory_Click"
CommandParameter
="{Binding Path=.}"/>
<MenuItem Header="Delete Category"
Click="DeleteItem_Click"
CommandParameter
="{Binding Path=.}"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</HierarchicalDataTemplate>

L'elemento ContextMenu specifica un semplice menu contestuale che permette l'aggiunta di una categoria. E la sua cancellazione. Per fare ciò è necessario che al metodo gestore dell'evento arrivi l'oggetto che corrisponde all'elemento dell'albero. Intendo cioè l'oggetto Category su cui è "bindato" il TreeViewItem su cui l'utente ha fatto click col tasto destro del mouse.
Uno stratagemma semplice è usare il CommandParameter con un espressione di binding come Path=.
In questa maniera il CommandParameter prenderà il valore dell'oggetto stesso e sarà inviato all'event handler:
private void DeleteItem_Click(object sender, RoutedEventArgs e)
{
Category cat = (Category)((MenuItem)sender).CommandParameter;
//Cancella la categoria...
}

Ovviamente questo trucco non si può utilizzare nel caso che si abbia effetivamente bisogno di valorizzare CommandParameter con qualcos'altro, ma in molti casi questo non è necessario.

Nessun commento: