具有多项选择的 WPF TreeView

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1163801/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 20:44:59  来源:igfitidea点击:

WPF TreeView with Multiple Selection

wpftreeviewmulti-select

提问by mark

The standard WPF tree viewdoes not support multiple selections.

标准 WPF树视图不支持多选。

How can I add a tree view that supports multiple selection to my WPF application? Commercial products are fine (I am currently aware of one commercial implementation - http://www.telerik.com/products/wpf/treeview.aspx)

如何将支持多选的树视图添加到我的 WPF 应用程序?商业产品很好(我目前知道一种商业实现 - http://www.telerik.com/products/wpf/treeview.aspx

回答by Kess

The code below works fine and is much simpler. However the draw back is the use of the non public property, IsSelectionChangeActive, of the treeview class. Code below:

下面的代码工作正常,而且更简单。然而,缺点是使用了树视图类的非公共属性 IsSelectionChangeActive。代码如下:

private static readonly PropertyInfo IsSelectionChangeActiveProperty 
  = typeof (TreeView).GetProperty
    (
      "IsSelectionChangeActive",
      BindingFlags.NonPublic | BindingFlags.Instance
    );

public static void AllowMultiSelection(TreeView treeView)
{
  if (IsSelectionChangeActiveProperty==null) return;

  var selectedItems = new List<TreeViewItem>();
  treeView.SelectedItemChanged += (a, b) =>
  {
    var treeViewItem = treeView.SelectedItem as TreeViewItem;
    if (treeViewItem == null) return;

    // allow multiple selection
    // when control key is pressed
    if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
    {
      // suppress selection change notification
      // select all selected items
      // then restore selection change notifications
      var isSelectionChangeActive = 
        IsSelectionChangeActiveProperty.GetValue(treeView, null);

      IsSelectionChangeActiveProperty.SetValue(treeView, true, null);
      selectedItems.ForEach(item => item.IsSelected = true);

      IsSelectionChangeActiveProperty.SetValue
      (
        treeView, 
        isSelectionChangeActive, 
        null
      );
    }
    else
    {
      // deselect all selected items except the current one
      selectedItems.ForEach(item => item.IsSelected = (item == treeViewItem) );
      selectedItems.Clear();
    }

    if (!selectedItems.Contains(treeViewItem))
    {
      selectedItems.Add(treeViewItem);
    }
    else
    {
      // deselect if already selected
      treeViewItem.IsSelected = false;
      selectedItems.Remove(treeViewItem);
    }
  };

}

回答by Ray Burns

Depending on the exact semantics you desire, the solution may be extremely simple:

根据您想要的确切语义,解决方案可能非常简单:

If the root of your tree is anything but a TreeView-- for example if it is a plain ItemsControl-- all TreeViewItems in the tree will be independently selectatble so you basically get mulitiselect for free. So just use an ItemsControlinstead of a TreeViewfor the root of your tree.

如果你的树的根不是一个TreeView——例如,如果它是一个普通的ItemsControl——树中的所有 TreeViewItems 将是独立的 selectatble,所以你基本上可以免费获得 multiselect。因此,只需对树的根使用 aItemsControl而不是 a TreeView

This solution has the benefit of being extraordinarily simple to implement. It differs from mattdlong's solution in that:

该解决方案的优点是实施起来非常简单。它与 mattdlong 的解决方案的不同之处在于:

  • His solution deselects all other items when an item is clicked, so you have to ctrl-click items to multiselect.
  • With this solution a single click will select/deselect the item you clicked on, but there is no way to quickly select an item and simultaneously deselect all others.
  • 他的解决方案在单击某个项目时取消选择所有其他项目,因此您必须按住 ctrl 单击项目才能进行多选。
  • 使用此解决方案,单击将选择/取消选择您单击的项目,但无法快速选择一个项目并同时取消选择所有其他项目。

Another difference is that keyboard navigation (arrow keys) in his solution deselects all items, whereas in this solution keyboard navigation does not deselect items.

另一个区别是他的解决方案中的键盘导航(箭头键)会取消选择所有项目,而在此解决方案中,键盘导航不会取消选择项目。

You should choose between these solutions based on the semantics you prefer (single click to add item vs ctrl-click to add item, etc). If you want more advanced semantics, such as Shift-Click, etc, it is relatively to add.

您应该根据您喜欢的语义在这些解决方案之间进行选择(单击添加项目与按住 ctrl 单击添加项目等)。如果想要更高级的语义,比如 Shift-Click 等,就比较添加了。

Note that you can also custom style TreeViewItems using a ToggleButtonor CheckBoxanywhere in the ItemContainerTemplatethat has Checked={Binding IsSelected}. This allows the user to select items by clicking on the ToggleButtonor CheckBox.

请注意,您还可以使用ToggleButtonCheckBoxItemContainerTemplate具有Checked={Binding IsSelected}. 这允许用户通过单击ToggleButton或来选择项目CheckBox