WPF TreeView 清除选择

10

如何在WPF TreeView中清除TreeView选中项?我尝试循环遍历TreeNodes并清除IsSelected属性,但该属性是只读的。有什么想法吗?

TreeView使用通过XMLDataProvider对象的XML绑定。

9个回答

13

我遇到了完全相同的问题,并编写了以下代码,该代码适用于任何树视图,并且只需调用第一个函数即可解决。

class TomWrightsUtils
{
    public static void ClearTreeViewSelection(TreeView tv)
    {
        if (tv != null)
            ClearTreeViewItemsControlSelection(tv.Items, tv.ItemContainerGenerator);
    }
    private static void ClearTreeViewItemsControlSelection(ItemCollection ic, ItemContainerGenerator icg)
    {
        if ((ic != null) && (icg != null))
            for (int i = 0; i < ic.Count; i++)
            {
                TreeViewItem tvi = icg.ContainerFromIndex(i) as TreeViewItem;
                if (tvi != null)
                {
                    ClearTreeViewItemsControlSelection(tvi.Items, tvi.ItemContainerGenerator);
                    tvi.IsSelected = false;
                }
            }
    }
}

8

我不确定你所说的TreeNodes是什么。

通常,你会在你的视图模型上有一个对应的IsSelected属性,供你的视图进行绑定:

<TreeView>
    <TreeView.ItemContainerStyle>
        <Style TargetType="TreeViewItem">
            <Setter Property="IsSelected" Value="{Binding IsSelected}"/>
        </Style>
    </TreeView.ItemContainerStyle>
</TreeView>

因此,您只需循环遍历视图模型中的数据项并在那里设置 IsSelected = false
但是,看起来您没有这样的属性。在这种情况下,您需要获取每个数据项的相应 TreeViewItem。有关如何执行此操作,请参见 TreeView.ItemContainerGenerator 属性。类似以下内容:
var treeViewItem = _treeView.ItemContainerGenerator.ContainerFromIndex(0) as TreeViewItem;
treeViewItem.IsSelected = false;

1
我急切地寻找选择TreeView中第一个索引的方法。我尝试了上面的解决方案(ContainerFromIndex),但它返回null。有什么帮助吗? - Shimmy Weitzhandler

6
TreeViewItem tvi = tvMain.ItemContainerGenerator.ContainerFromIndex(0) as TreeViewItem;

if (tvi != null) { tvi.IsSelected = true; tvi.IsSelected = false; }

这是唯一真正的解决方案。 - PigSpider
清晰简洁应该是最佳答案。 - Jesse
这是一个解决方案,虽然简短,但感觉有点不太好。通过选择根节点取消选择,然后再次取消选择。尽管如此,它可能比涉及遍历树的解决方案更高效。 - tjmoore

2
这很适合作为扩展方法,这样你就可以调用它。
youTreeview.ClearSelection();

using System.Windows.Forms;
using System.Windows.Controls;

namespace YourAppNamespace
{
    public static void ClearSelection(this TreeView input)
    {
    // this should be some container that you put in
    // possibly the actual treeviewitem, not sure on that though
    var selected = input.SelectedItem;
    if (selected == null)
        return;

    // in my case this works perfectly
    var tvi = input.ItemContainerGenerator.ContainerFromItem(selected) as TreeViewItem;
    var tvi = input.ItemContainerGenerator.ContainerFromItem(selected) as TreeViewItem;
    if (tvi == null)
    {
        // it must be a child, heres a hack fix
        // my nodes are inherited from TreeViewItemViewModel by Josh Smith
        var child = selected as WPF.Controls.TreeViewItemViewModel;
        if (child == null)
            return;
        child.IsSelected = false;

    }
    else
        tvi.IsSelected = false;
     }


}

2

查找所选项目并设置其值:

private void Button_Click(object sender, RoutedEventArgs e)
{
  TreeViewItem tvi = treeviewExample.SelectedItem as TreeViewItem;
  if (tvi != null)
  {
    tvi.IsSelected = false;
  }
}

1

根据我的经验,我建议避免使用标准的ItemContainerGenerator调用,因为它们会在深度大于n+1的节点上失败。我使用以下扩展方法的组合。ContainerFromItem扩展方法来自MSDN博客,当处理TreeView时,它对我非常有帮助。

  public static void ClearSelection(this TreeView input)
  {
     var selected = input.SelectedItem;

     if (selected == null) return;

     var tvi = input.ContainerFromItem(selected) as TreeViewItem;

     if (tvi == null) return;

     tvi.IsSelected = false;

  }

  public static TreeViewItem ContainerFromItem(this TreeView treeView, object item)
  {
     TreeViewItem containerThatMightContainItem = (TreeViewItem)treeView.ItemContainerGenerator.ContainerFromItem(item);
     if (containerThatMightContainItem != null)
        return containerThatMightContainItem;
     else
        return ContainerFromItem(treeView.ItemContainerGenerator, treeView.Items, item);
  }

  private static TreeViewItem ContainerFromItem(ItemContainerGenerator parentItemContainerGenerator, ItemCollection itemCollection, object item)
  {
     foreach (object curChildItem in itemCollection)
     {
        TreeViewItem parentContainer = (TreeViewItem)parentItemContainerGenerator.ContainerFromItem(curChildItem);
        if (parentContainer == null)
           return null;
        TreeViewItem containerThatMightContainItem = (TreeViewItem)parentContainer.ItemContainerGenerator.ContainerFromItem(item);
        if (containerThatMightContainItem != null)
           return containerThatMightContainItem;
        TreeViewItem recursionResult = ContainerFromItem(parentContainer.ItemContainerGenerator, parentContainer.Items, item);
        if (recursionResult != null)
           return recursionResult;
     }
     return null;
  }

0

我刚遇到了同样的问题。

一个快速而简单的解决方案

tree.ItemsSource = null;

tree.ItemsSource = yourSource;

0

目前看来这个方法似乎是可行的,但我只是五分钟之前刚加入,所以使用时请自行承担风险。我基本上想在用户在树形控件内单击时清除选择内容,但不希望在单击树项时清除。

 void DestinationTree_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
 {
     TreeView tree = sender as TreeView;
     DestinationClientViewModel selectedItem = tree.SelectedItem as DestinationClientViewModel;

     if (selectedItem != null)
     {
        int selectedItemIndex = this.DestinationTree.Items.IndexOf(selectedItem);

        if (selectedItemIndex > -1)
        {
            TreeViewItem tvi = this.DestinationTree.ItemContainerGenerator.ContainerFromIndex(selectedItemIndex) as TreeViewItem;
            if (tvi != null)
                tvi.IsSelected = false;
        }
     }
 }

请忽略我的代码。仅适用于根级别。选择任何子节点都不会被清除。 - Ben Dempsey

0

我在使用自定义的树形列表视图实现时遇到了这种情况,经过长时间的寻找,我终于找到了适合我的解决方案。

完整的解释可以在http://social.msdn.microsoft.com/Forums/vstudio/en-US/36aca7f7-0b47-488b-8e16-840b86addfa3/getting-treeviewitem-for-the-selected-item-in-a-treeview中找到。

基本思路是捕获TreeViewItem.Selected事件,并将事件源保存到您的TreeView的Tag属性中。然后当您需要清除它时,您可以访问您控件上的Tag属性,并将IsSelected值设置为False。对于我来说,这适用于两个级别的嵌套子项。希望它也适用于您。

为了持久性:

TreeView声明

  <TreeView Name="myTreeView" TreeViewItem.Selected="OnItemSelected"
    ItemsSource="{Binding Source={StaticResource myHierarchicalData}}"/>

事件处理程序

private void OnItemSelected(object sender, RoutedEventArgs e)
{
    myTreeView.Tag = e.OriginalSource;
}

清除选择逻辑
if (myTreeView.SelectedItem != null)
{
    TreeViewItem selectedTVI = myTreeView.Tag as TreeViewItem;
    // add your code here mine was selectedTVI.IsSelected = false;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接