2
votes

I've got a TreeView that uses a HierarchicalDataTemplate and a view model as data context on different nodes. I want to access some TreeViewItem properties from TreeView.SelectedItem - but this returns a view model object not a TreeViewItem.
How to get a TreeViewItem ref to selected item?
(Ive the same problem in SelectedItemChanged handlers - object sender is a view model - how to get TreeViewItem?)
[There is a TreeView property SelectedContainer which returns a TreeViewItem but its not accessable :-( ]

This is the kind of frustrating thing about WFP is that is easy to get stuck on this kind of "detail" and it seems like there must be an easy/obvious solution but...

3

3 Answers

2
votes

Once you've bound your TreeView to a data context, you will always get back view-model objects. If you want to manipulate TreeViewItem objects in response to events, you need to do it through bindings. For example, the IsExpanded, IsSelected properties can be tied to view-model properties by using styles. The following code automatically bolds the selected tree item and binds the aforementioned properties to view-model properties where I can manipulate/read them.

        <TreeView x:Name="treeEquipment"
              ItemsSource="{Binding RootEquipment}" 
        <TreeView.ItemContainerStyle>
            <Style TargetType="{x:Type TreeViewItem}">
                <EventSetter Event="TreeViewItem.MouseRightButtonDown"
                             Handler="TreeViewItem_MouseRightButtonDown"/>
                <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
                <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
                <Setter Property="FontWeight" Value="Normal" />
                <Style.Triggers>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter Property="FontWeight" Value="Bold" />
                    </Trigger>
                </Style.Triggers>
            </Style> 
        </TreeView.ItemContainerStyle>
0
votes

The property I was trying to set was IsSelected which I always wanted false because I manage multiple selection my self. Following StrayPointers advice that works with a binding on the view mode:

class TreeNodeViewMode {
    public bool no_selection {
        get { return false; }
        set { RaisePropertyChanged(); }
    }
}

XAML:

<TreeView.ItemContainerStyle>
    <Style TargetType="{x:Type TreeViewItem}">
        <Setter Property="IsSelected" Value="{Binding no_selection, Mode=TwoWay}" />
    </Style>
</TreeView.ItemContainerStyle>
0
votes

Another approach is to handle TreeViewItem.Selected event which unlike TreeView.SelectedItemChanged (which gets a view model passed in) this does get us the TreeViewItem via:

TreeViewItem item = e.OriginalSource as TreeViewItem;

Which enables the setting of properties eg

TreeViewItem item = e.OriginalSource as TreeViewItem;
if (item != null) {
    item.Focus();
    item.IsSelected = false;
}