Onion-Knight
Onion-Knight

Reputation: 3555

Attaching Event Handlers to Dynamically Created TreeViewItems

Preamble:

I have the following XAML:

<controls:TreeView x:Name="tv">
    <controls:TreeViewItem x:Name="tvi" Header="RootNodeTitle" IsExpanded="True">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <controls:TreeViewItem Header="{Binding TextToBindTo}" Selected="TreeViewItem_Selected" />
            </DataTemplate>
         </ItemsControl.ItemTemplate>
     </controls:TreeViewItem>
</controls:TreeView>

And the following .NET code-behind:

_viewCollection = New CollectionViewSource()
_viewCollection.Source = _data.RoleList
tvi.ItemsSource = _viewCollection.View

Problem:

I want to attach an event handler to the Selected event of tvi's children (that are dynamically generated based on databinding.

I've tried to use the Selected="..." markup (as shown in the XAML) in the ItemTemplate, but this does not work.

Question:

How can this be done?

Upvotes: 0

Views: 279

Answers (1)

Silver Solver
Silver Solver

Reputation: 2320

I'm not sure why the Selected event isn't handled on that nested TreeViewItem, but if we change it a little to set the ItemsSource on the TreeView, it does get handled:

<controls:TreeView x:Name="tv"  SelectedItemChanged="tv_SelectedItemChanged">
        <controls:TreeView.ItemTemplate>
            <DataTemplate>
                <!-- this Selected event handler does get called -->
                <controls:TreeViewItem Header="{Binding Name}" Selected="TreeViewItem_Selected" >
...

The event that is raised however does not contain any useful information about the item so you cannot sensibly derive anything useful from that event.

Setting a handler for the SelectedItemChanged event on the TreeView works and also contains the usual OldValue and NewValue properties in the EventArgs.

The event also fires for all TreeViewItems - nested or not.

Try this:

<controls:TreeView x:Name="tv"  SelectedItemChanged="tv_SelectedItemChanged">
    <controls:TreeViewItem x:Name="tvi" Header="RootNodeTitle" IsExpanded="True" Selected="TreeViewItem_Selected" >
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <controls:TreeViewItem Header="{Binding}" Selected="TreeViewItem_Selected" >
                    <Border Background="Black" Height="25" Width="25" />
                </controls:TreeViewItem>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </controls:TreeViewItem>
</controls:TreeView>

...

void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    tvi.ItemsSource = GetItems();

}

private IEnumerable GetItems()
{
    for (int i = 0; i < 10; i++)
    {
        yield return i;
    }
}

private void tv_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
    var oldItem = e.OldValue;
    var newItem = e.NewValue;
}

Upvotes: 1

Related Questions