1
votes

I am (trying to) build a TreeView of the file system (Nodes are directories, leaves are files).

I have the xaml to do the data binding, but I cannot get the TreeViewItem selected event to fire (or I cannot detect it).

<Window x:Class="List.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:List"
        xmlns:dmodels="clr-namespace:List.DataModels"
        Title="MainWindow" Height="350" Width="525">

        <Window.Resources>
            <ResourceDictionary>
            <HierarchicalDataTemplate DataType="{x:Type dmodels:DirectoryNode}" ItemsSource="{Binding Children}">
                <TreeViewItem FontSize="16" FontWeight="Bold" Header="{Binding Path=DisplayName}" Selected="TVI_Selected" >
                        <TextBlock Text="Please Wait..." MouseDown="Listbox1_MouseLeftButtonDown"  />
                </TreeViewItem>
            </HierarchicalDataTemplate>
            <DataTemplate DataType="{x:Type dmodels:FileNode}">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Margin="20,0,0,0" Text="{Binding Path=DisplayName}" FontWeight="Bold" MouseDown="Listbox1_MouseLeftButtonDown"  />
                    </StackPanel>
            </DataTemplate>
        </ResourceDictionary>
        </Window.Resources>

    <Grid>
        <TreeView x:Name="myTree" ItemsSource="{Binding Files}" SelectedItemChanged="TreeSelectionChanged" >
        </TreeView>
    </Grid>
</Window>

I have the 'Node (directory)' displayed as a TreeViewItem (so that I can get the expander toggle), but when it is either clicked, or double-clicked, the TVI_Selected method does not get called. When the Leaf (file)' is clicked, or double-clicked, the TreeSelectionChanged method DOES get called, but it is not a TreeViewItem (to suppress the expander toggle).

I want to intercept the Selected event so that I can replace the "Please Wait..." with the appropriate children data.

Since I am new to this, there is high probability that I am doing something stupid, or badly, or just don't get it -- if there is a better way to do any of this, I'd love to hear it.

private void  TVI_Selected ( object sender, RoutedEventArgs e )
{
    Console.WriteLine ( " TreeViewItem selection Changed " );
}

private void TreeSelectionChanged ( object sender, RoutedPropertyChangedEventArgs<Object> e )
{
    //Perform actions when SelectedItem changes
    BaseNode node = e.NewValue as BaseNode;

    if (node != null)
    {
        string str = node.DisplayName;
        string s2  = (node.IsDirectory == true) ? "Directory" : "File";
        Console.WriteLine ( " tree selection = {0} is a {1}", str, s2 );
    }
}
1

1 Answers

4
votes

I think that your problem might lie in your HierarchicalDataTemplate. You're not supposed to declare an TreeViewItem there as the TreeView will automatically wrap what you define in the DataTemplate in a TreeViewItem anyway. Try removing it and defining the child items in the HierarchicalDataTemplate.ItemTemplate property:

<HierarchicalDataTemplate DataType="{x:Type dmodels:DirectoryNode}"
    ItemsSource="{Binding Children}">
    <StackPanel>  <!-- Define parent items here-->
        <TextBlock FontSize="16" FontWeight="Bold" Text="{Binding Path=DisplayName}">
        <TextBlock Text="Please Wait..." MouseDown="Listbox1_MouseLeftButtonDown" />
    </StackPanel>
    <HierarchicalDataTemplate.ItemTemplate> 
        <DataTemplate>
            <TextBlock Text="{Binding Name}" /> <!-- Define child items here-->
        </DataTemplate> 
    </HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>

For more information, please see the TreeView and HierarchicalDataTemplate, Step-by-Step page from Mike Hillberg's Blog on Wpf and Silverlight on MSDN.