How to get TreeViewItem from HierarchicalDataTemplate item?

前端 未结 11 1395
失恋的感觉
失恋的感觉 2020-12-02 11:34

I have a TreeView which uses a HierarchicalDataTemplate to bind its data.

It looks like this:



        
相关标签:
11条回答
  • 2020-12-02 11:53
    TreeViewItem item = (TreeViewItem)(mainTreeList
        .ItemContainerGenerator
        .ContainerFromIndex(mainTreeList.Items.CurrentPosition)); gives first item in the TreeView because CurrentPosition is always 0.
    

    How about

    TreeViewItem item = (TreeViewItem)(mainTreeList
        .ItemContainerGenerator
        .ContainerFromItem(mainTreeList.SelectedItem)));
    

    This works better for me.

    0 讨论(0)
  • 2020-12-02 11:59

    From Bea Stollnitz's blog entry about this, try

    TreeViewItem item = (TreeViewItem)(mainTreeList
        .ItemContainerGenerator
        .ContainerFromIndex(mainTreeList.Items.CurrentPosition));
    
    0 讨论(0)
  • 2020-12-02 12:00

    A single 'ItemContainerGenerator.ContainerFromItem' or 'ItemContainerGenerator.ItemContainerGenerator' call cannot find the TreeViewItem associated by tree view object, since the separation of tree view item controller and tree view item data. It is necessary to create a recursive function to use 'ItemContainerGenerator.ContainerFromItem' and 'ItemContainerGenerator.ItemContainerGenerator', to locate TreeViewItem in tree view. Example recursive function could look like:

    private TreeViewItem GetTreeViewItemFromObject(ItemContainerGenerator container, object tvio)
    {
        var item = container.ContainerFromItem(tvio) as TreeViewItem;
        if (item != null)
        {
            return item;
        }
    
        for (int i = 0; i < container.Items.Count; i++)
        {
            var subContainer = (TreeViewItem)container.ContainerFromIndex(i);
            if (subContainer != null)
            {
                item = GetTreeViewItemFromObject(subContainer.ItemContainerGenerator, tvio);
                if (item != null)
                {
                    return item;
                }
            }
        }
    
        return null;
    }
    

    called by var target = GetTreeViewItemFromObject(treeView.ItemContainerGenerator, item);

    The recursive function only works after tree view's 'ItemContainerGenerator.Status' is 'ContainersGenerated'. So during the initialization view period, 'GetTreeViewItemFromObject' does not work.

    0 讨论(0)
  • 2020-12-02 12:02

    I ran into this same problem. I needed to get to the TreeViewItem so that I could have it be selected. I then realized that I could just add a property IsSelected to my ViewModel, which I then bound to the TreeViewItems IsSelectedProperty. This can be achieved with the ItemContainerStyle:

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

    Now if I want to have an item in the treeview selected, I just call IsSelected on my ViewModel class directly.

    Hope it helps someone.

    0 讨论(0)
  • 2020-12-02 12:03
    TreeViewItem item = (TreeViewItem)(mainTreeList
        .ItemContainerGenerator
        .ContainerFromIndex(mainTreeList.Items.CurrentPosition));
    

    DOES NOT WORK (for me) as mainTreeList.Items.CurrentPosition in a treeview using a HierarchicalDataTemplate will always be -1.

    NEITHER DOES below as as mainTreeList.Items.CurrentItem in a treeview using a HierarchicalDataTemplate will always be null.

    TreeViewItem item = (TreeViewItem)mainTreeList
        .ItemContainerGenerator
        .ContainerFromItem(mainTreeList.Items.CurrentItem);
    

    INSTEAD I had to set a the last selected TreeViewItem in the routed TreeViewItem.Selected event which bubbles up to the tree view (the TreeViewItem's themselves do not exist at design time as we are using a HierarchicalDataTemplate).

    The event can be captured in XAML as so:

    <TreeView TreeViewItem.Selected="TreeViewItemSelected" .../> 
    

    Then the last TreeViewItem selected can be set in the event as so:

        private void TreeViewItemSelected(object sender, RoutedEventArgs e)
        {
            TreeViewItem tvi = e.OriginalSource as TreeViewItem;
    
            // set the last tree view item selected variable which may be used elsewhere as there is no other way I have found to obtain the TreeViewItem container (may be null)
            this.lastSelectedTreeViewItem = tvi;
    
            ...
         }
    
    0 讨论(0)
  • 2020-12-02 12:03

    Try something like this:

        public bool UpdateSelectedTreeViewItem(PropertyNode dateItem, ItemsControl itemsControl)
        {
            if (itemsControl == null || itemsControl.Items == null || itemsControl.Items.Count == 0)
            {
                return false;
            }
            foreach (var item in itemsControl.Items.Cast<PropertyNode>())
            {
                var treeViewItem = itemsControl.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
                if (treeViewItem == null)
                {
                    continue;
                }
                if (item == dateItem)
                {
                    treeViewItem.IsSelected = true;
                    return true;
                }
                if (treeViewItem.Items.Count > 0 && UpdateSelectedTreeViewItem(dateItem, treeViewItem))
                {
                    return true;
                }
            }
            return false;
        }
    
    0 讨论(0)
提交回复
热议问题