0
votes

I've seen many examples of how to perform this task (I sure have looked), but one line that seems to appear again and again is the following:

TreeViewItem item = e.OriginalSource as TreeViewItem;

Which makes sense. The problem is that, no matter what I click on in my treeview, item is always null.

My treeview has two layers. The top level is Scenes and the bottom level is characters. Each scene contains one more more characters. My aim is to be able to know the scene when the character is selected.

I suppose maybe my TreeView might be done differently to a lot of people's, so I shall provide that too:

<TreeView x:Name="ScenesTreeView01" Grid.Column="0" Width="Auto" Background="AliceBlue" ItemsSource="{Binding Scenes}" SelectedItemChanged="TreeView_SelectedItemChanged" BorderThickness="0">
        <TreeView.DataContext>
            <viewModels:ScenesViewModel />
        </TreeView.DataContext>
        <TreeView.Resources>
            <ContextMenu x:Key="SceneLevel">
                            <MenuItem Header="Add selected character" Command="{Binding Path=DataContext.AddSelectedCharacter, Source={x:Reference ScenesTreeView01}}"/>
            </ContextMenu>
            <ContextMenu x:Key="CharacterLevel">
                            <MenuItem Header="Remove character from scene" Command="{Binding Path=DataContext.RemoveCharacterFromScene, Source={x:Reference ScenesTreeView01}}"/>
            </ContextMenu>
        </TreeView.Resources>
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding Characters}">
                    <StackPanel Orientation="Horizontal" ContextMenu="{StaticResource SceneLevel}">
                    <TextBlock Text="{Binding SceneName}"></TextBlock>

                        <Image Source="{StaticResource ImgBook1}" Margin="0,0,5,0" Width="32" Height="32"/>

                </StackPanel>
                <HierarchicalDataTemplate.ItemTemplate>
                    <DataTemplate>
                        <Border BorderThickness="2" BorderBrush="LightBlue" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="2" CornerRadius="5,5,5,5">
                            <StackPanel Orientation="Horizontal" Margin="3" ContextMenu="{StaticResource CharacterLevel}">

                            <TextBlock FontFamily="Levenim MT" FontSize="16" VerticalAlignment="Center" MinWidth="50" Text="{Binding FirstName}"></TextBlock>

                                <Image Source="{Binding ImgIcon}" Margin="2" Width="32" Height="32"/>

                        </StackPanel>
                        </Border>
                    </DataTemplate>
                </HierarchicalDataTemplate.ItemTemplate>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>

e.OriginalSource does give something though, and that's this: System.Windows.Controls.TreeView Items.Count:4. I get that whether I select the top level or the bottom level (the top level has four items, the bottom levels have three each).

If someone could lend an eye to help me with this, that would be greatly appreciated. Thanks.

2
The message your'e getting from e.OriginalSource means that OriginalSource is an instance of System.Windows.Controls.TreeView instead of System.Windows.Controls.TreeView and that's why you get null every time you try to safe-cast it as TreeViewItem - Karel Tamayo

2 Answers

0
votes

If you are binding, you won't get TreeViewItem any longer, but the collection items from your viewmodel/datacontext.

As far as the parent is concerned, I'd suggest to define it as a property of the above said viewmodel class.

I have a project/sample with a tree view on github

0
votes

You could try to cast the NewValue property of the RoutedPropertyChangedEventArgs<object> to your Character type:

private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
    Character c = e.NewValue as Character;
    if (c != null)
    {
        //a character was selected...
    }
}

This property should contain the newly selected item and if the cast succeeds you know that a Character was selected.

You should then be able to access a parent property or something of this class to get a reference to the parent scene.