0
<TreeView Name="MyTreeView" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling">
    <TreeView.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel IsItemsHost="True"/>
        </ItemsPanelTemplate>
    </TreeView.ItemsPanel>
    <TreeView.Resources>
        <DataTemplate DataType="{x:Type EntityType:MyFixedDevice}">
            <TreeViewItem IsHitTestVisible="True" IsEnabled="True">
            <TreeViewItem.Header>
                <TextBlock Text="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource NameConverter}}"
                           IsHitTestVisible="True" IsEnabled="True"/>
            </TreeViewItem.Header>
            </TreeViewItem>
        </DataTemplate>
    </TreeView.Resources>
    <TreeView.Items>
        <TreeViewItem Header="Data Warehouse">
            <TreeViewItem.Items>
                <TreeViewItem Header="Platforms">
                   <TreeViewItem.Items>
                       <TreeViewItem ItemsSource="{Binding OBJS, Converter={StaticResource COBJSourceConverter}, ConverterParameter=Fixed}">
                           <TreeViewItem.Header>
                               <TextBlock Text="{Binding RelativeSource={RelativeSource Self},
                                          Path=Parent.Items.Count,
                                          StringFormat=Fixed Devices ({0})}">
                               </TextBlock>
                           </TreeViewItem.Header>
                       </TreeViewItem>
                  </TreeViewItem.Items>
                </TreeViewItem>
            </TreeViewItem.Items>
        </TreeViewItem>
    </TreeView.Items>
</TreeView>

How come left-click on the TreeViewItems that are created with DataTemplate does not select them? How come if I select them in code, I can't select them again or deselect them?

TreeViewItem selectedItem = MyTreeView.SelectedItem as TreeViewItem;
if(selectedItem != null) {
    selectedItem.IsSelected = false;
    MyTreeView.Focus();
}

I've tried to use the below to unselect TreeViewItems in the TreeView, but it only deselects the TreeViewItems if they are statically set in the XAML, and not if they are created using an ItemsSource and DataTemplate?

Bob.
  • 3,894
  • 4
  • 44
  • 76

2 Answers2

1

When you set ItemSource the SelectedItem corresponds to the DataContext type as in your Type T of the ItemSource collection you set, not the actual TreeViewItem.

hence why your cast fails.

Now when you create them in xaml directly without setting the ItemSource, SelectedItem is just the TreeViewitem itself and the as cast works fine.

Update:

It has nothing to with your DataTemplate

try this:

<Window.Resources>
  <x:Array x:Key="someArray"
            Type="sys:String">
    <sys:String>Hello</sys:String>
    <sys:String>World</sys:String>
  </x:Array>
</Window.Resources>
<StackPanel>
  <TreeView x:Name="MyTreeView"
            ItemsSource="{DynamicResource someArray}" />
  <Button Click="ButtonBase_OnClick"
          Content="Some" />
</StackPanel>

and code-behind:

private void ButtonBase_OnClick(object sender, RoutedEventArgs e) {
  TreeViewItem selectedItem = MyTreeView.SelectedItem as TreeViewItem;
  if (selectedItem != null) {
    selectedItem.IsSelected = false;
    MyTreeView.Focus();
  } else {
    Debug.WriteLine("Not TreeViewitem");
    Debug.WriteLine(MyTreeView.SelectedItem);
  }
}

now when app is run click on an item and then click the Button

check the output Window and you'll see

Not TreeViewitem
Hello

DataTemplate merely helps visualize a custom Datatype in the View. This is intended behavior when a collection is bound to the TreeView

Solution:

in your case to get the Actual TreeViewItem try:

private void ButtonBase_OnClick(object sender, RoutedEventArgs e) {
  TreeViewItem selectedItem =
    MyTreeView.ItemContainerGenerator.ContainerFromItem(MyTreeView.SelectedItem) as TreeViewItem;
  if (selectedItem == null)
    return;
  selectedItem.IsSelected = false;
  MyTreeView.Focus();
}

^^ this supposedly does not work for HierarchicalDataTemplate. Refer to this for more options.

Community
  • 1
  • 1
Viv
  • 17,170
  • 4
  • 51
  • 71
  • But I use a `DataTemplate` to create a `TreeViewItem` for Type `T`. – Bob. Jul 10 '13 at 15:04
  • @Bob. it has nothing to do with your `DataTemplate` check my update to the answer. – Viv Jul 10 '13 at 15:11
  • @Bob. for your requirement I've added a solution at the bottom of my answer. Try and see if that works for you. – Viv Jul 10 '13 at 15:25
1

Are you actually going to do something special with the TreeViewItem template for your fixed devices (that requires altering the TreeViewItem template?

On the face of it, it seems like you could let the TreeView take care of its own items, and just use a simple template for your object representation: e.g.

<DataTemplate DataType="{x:Type EntityType:MyFixedDevice}">
    <TextBlock Text="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource NameConverter}}" />
</DataTemplate>

I may have misunderstood what you're trying to achieve.

Chris
  • 8,268
  • 3
  • 33
  • 46
  • Hmm... I thought that I'd need to create a `TreeViewItem` object to go into the `TreeViewItem.Items` or it wouldn't be treated as such, but this works for me. – Bob. Jul 10 '13 at 19:02
  • I believe, because `TreeView` inherits from an `ItemsControl`, that it will automatically wrap all it's items in the appropriate container (`TreeViewItem`). I imange putting another `TreeViewItem` in the template meant that it was wrapped twice, and things got a bit confusing. – Chris Jul 10 '13 at 21:40