单击某个空白区域时,如何取消选择 WPF 树视图中的所有选定项目?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/491111/
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
How to deselect all selected items in a WPF treeview when clicking on some empty area?
提问by Anteru
I've got a rather funny problem with WPF. I have a tree-view, and selecting items works fine so far. The problem is, I want to unselect the currently selected item when the user clicks inside the blank area of the treeview. By default, the treeview keeps the current item selected, and I have added a context-menu option to deselect it, which is rather hardcore:
我对 WPF 有一个相当有趣的问题。我有一个树视图,到目前为止选择项目工作正常。问题是,当用户在树视图的空白区域内单击时,我想取消选择当前选定的项目。默认情况下,树视图保持当前项目处于选中状态,并且我添加了一个上下文菜单选项来取消选择它,这是相当核心的:
// Note: This is done recursivly from the start, so it
// works for child items as well
treeView.ItemContainerGenerator.ContainerFromItem(treeView.SelectedItem) as TreeViewItem).IsSelected = false;
Moreover, this is counter-intuitive, as it requires the user to right-click first, and second, after deselecting it with this way, the user cannot select it any more by clicking on the item. How is this supposed to work?
此外,这是违反直觉的,因为它要求用户首先右键单击,其次,通过这种方式取消选择后,用户无法再通过单击该项目来选择它。这应该如何工作?
Edit: Some more information: I've added a handler to the TreeView
to handle mouse click events, but the sender is always a TreeView
instance, even if I click directly on a TreeViewItem
. If I add a handler to my TreeView.ItemTemplate
instead (i.e. the first child in the template), I never get events when I click on the empty area (which is rather logical). The code looks like this:
编辑:更多信息:我添加了一个处理程序来TreeView
处理鼠标单击事件,但发送者始终是一个TreeView
实例,即使我直接单击TreeViewItem
. 如果我向我添加一个处理程序TreeView.ItemTemplate
(即模板中的第一个孩子),当我点击空白区域时我永远不会收到事件(这是相当合乎逻辑的)。代码如下所示:
private void MyTreeView_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if ((sender as TreeViewItem) == null)
{
// Always triggered
System.Diagnostics.Trace.Write("Empty area clicked");
}
}
And the XAML for this is:
用于此的 XAML 是:
<TreeView x:Name="MyTreeView" Margin="3" MouseUp="MyTreeView_MouseUp">
回答by Erin
I found this to work much better for me. I check the originalsource which for me if it comes form a treeviewitem will be an image or a textblock. I also use a view object with a HierarchicalDataTemplate and the BasicTreeViewBase is the base class for all of my different objects. Here is the code.
我发现这对我来说效果更好。我检查原始源,如果它来自树视图项,它将是图像或文本块。我还使用了一个带有 HierarchicalDataTemplate 的视图对象,而 BasicTreeViewBase 是我所有不同对象的基类。这是代码。
private void TemplateTreeView_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Right && !(e.OriginalSource is Image) && !(e.OriginalSource is TextBlock))
{
BasicTreeViewBase item = TemplateTreeView.SelectedItem as BasicTreeViewBase;
if (item != null)
{
TemplateTreeView.Focus();
item.IsSelected = false;
}
}
}
回答by Robert Macnee
The un-selectable problem can be solved with a call to Focus on the TreeView after setting TreeViewItem.IsSelected.
在设置 TreeViewItem.IsSelected 后调用 Focus on the TreeView 可以解决不可选择的问题。
回答by Ugo Robain
There can be two more problem :
可能还有两个问题:
- The treeview is binded so the SelectedItem is an item of the binded collection.
- There is many levels so ItemContainerGenerator do not contain deepest level objects
- 树视图已绑定,因此 SelectedItem 是绑定集合的一个项目。
- 有很多层次,所以 ItemContainerGenerator 不包含最深层次的对象
for all this reason i use this function, but the selection must not fire any events.
出于所有这些原因,我使用此功能,但选择不得触发任何事件。
private void UnselectTreeViewItem(TreeView pTreeView)
{
if(pTreeView.SelectedItem == null)
return;
if(pTreeView.SelectedItem is TreeViewItem)
{
(pTreeView.SelectedItem as TreeViewItem).IsSelected = false;
}
else
{
TreeViewItem item = pTreeView.ItemContainerGenerator.ContainerFromIndex(0) as TreeViewItem;
if (item != null)
{
item.IsSelected = true;
item.IsSelected = false;
}
}
}
回答by Asaf Pala
Use the extension class below
使用下面的扩展类
public static class TreeViewExtensions
{
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);
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;
}
}
Then in MouseDown event of treeview use the extension method as below:
然后在 treeview 的 MouseDown 事件中使用如下扩展方法:
private void trview_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if ((sender as TreeViewItem) == null)
{
if (this.trview.ContainerFromItem(trview.SelectedItem) != null)
{
this.trview.ContainerFromItem(trview.SelectedItem).IsSelected = false;
}
}
this.trview.Focus();
}
Hope it works for you. I have it working in this way...
希望对你有效。我让它以这种方式工作......
回答by Kenan E. K.
I implemented a general selection control once, and required this behaviour.
我实现了一次通用选择控制,并且需要这种行为。
This is how my method looked (adapted for treeview):
这是我的方法的外观(适用于树视图):
protected override void OnMouseUp(MouseButtonEventArgs e)
{
base.OnMouseUp(e);
DependencyObject dpSource = e.OriginalSource as DependencyObject;
if (dpSource.FindVisualAncestor(o => typeof(TreeViewItem).IsAssignableFrom(o.GetType())) == null)
UnselectAll();
}
Basically, walk up the tree from the source. If a TreeViewItem was not found, than the user clicked empty space.
基本上,从源头上走树。如果未找到 TreeViewItem,则用户单击空白区域。
回答by Philter
I was running into this situation myself with a custom Tree List View implementation after looking for a long time I finally found a solution that worked for me.
在寻找了很长时间后,我自己使用自定义树列表视图实现遇到了这种情况,我终于找到了一个对我有用的解决方案。
The full explanation can be found at http://social.msdn.microsoft.com/Forums/vstudio/en-US/36aca7f7-0b47-488b-8e16-840b86addfa3/getting-treeviewitem-for-the-selected-item-in-a-treeview
完整的解释可以在http://social.msdn.microsoft.com/Forums/vstudio/en-US/36aca7f7-0b47-488b-8e16-840b86addfa3/getting-treeviewitem-for-the-selected-item-in找到-a-treeview
The basic idea is you capture the TreeViewItem.Selected
event and save the source of the event into the Tag
attribute on your TreeView. Then when you need to clear it, you can access the Tag
attribute on your control and set the IsSelected
value to False. This works for me with 2 levels of nested children. Hopefully it will work for you.
基本思想是捕获TreeViewItem.Selected
事件并将事件源保存到Tag
TreeView 上的属性中。然后当您需要清除它时,您可以访问Tag
控件上的属性并将IsSelected
值设置为 False。这对我有 2 个级别的嵌套子项有效。希望它对你有用。
For persistence sake:
为了坚持:
TreeView declaration
树视图声明
<TreeView Name="myTreeView" TreeViewItem.Selected="OnItemSelected"
ItemsSource="{Binding Source={StaticResource myHierarchicalData}}"/>
Event Handler
事件处理程序
private void OnItemSelected(object sender, RoutedEventArgs e)
{
myTreeView.Tag = e.OriginalSource;
}
Clear selection logic
清晰的选择逻辑
if (myTreeView.SelectedItem != null)
{
TreeViewItem selectedTVI = myTreeView.Tag as TreeViewItem;
// add your code here mine was selectedTVI.IsSelected = false;
}
回答by Mark Carpenter
This will deselect the currently selected TreeViewItem if none were clicked:
如果没有单击,这将取消选择当前选定的 TreeViewItem:
private void MyTreeView_PreviewMouseDown(object sender, MouseButtonEventArgs e) {
if ((sender as TreeViewItem) == null) {
TreeViewItem item = MyTreeView.SelectedItem as TreeViewItem;
if(item != null){
item.IsSelected = false;
}
}
}
Hope this is what you were looking for!
希望这就是你要找的!
回答by Dan Gifford
For a C# treeview you use treeview.SelectedNode = null; I'm not sure if this works for WPF.
对于 C# 树视图,您使用 treeview.SelectedNode = null; 我不确定这是否适用于 WPF。