2009-01-29 35 views
9

我对WPF有一个相当有趣的问题。我有一个树形视图,选择项目到目前为止工作得很好。问题是,我想在用户点击树形视图的空白区域时取消选择当前选定的项目。默认情况下,树形视图保持当前的项目选择,我添加了一个上下文菜单选项来取消它,这是相当硬派:如何在点击某个空白区域时取消选择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; 

此外,这是反直觉的,因为它需要用户右键单击第一个,第二个,用这种方式取消选择后,用户不能再通过单击该项目来选择它。这应该如何工作?

编辑:一些详细信息:我添加了一个处理程序的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"); 
     } 
    } 

而且这样做的XAML是:

<TreeView x:Name="MyTreeView" Margin="3" MouseUp="MyTreeView_MouseUp"> 

回答

0

这将取消当前选择的树型视图,如果没有被点击:

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;      
     } 
    } 
} 

希望这是什么你正在寻找!

+0

不起作用,因为在选择一个项目后,发件人会绑定到当前选定的项目 - 即,即使我点击空白区域,发件人==当前选定的项目。 – Anteru 2009-01-30 08:51:14

+0

嗯。如果您单击TreeView本身,发件人应该是TreeView(而不是TreeViewItem)。您是否将此处理程序添加到TreeView或每个TreeViewItem?你使用标准的TreeView还是自定义的? – Pwninstein 2009-01-30 12:24:31

+0

啊,问题是我没有得到一个TreeViewItem,而是我的viewmodel类的一个实例,为此我必须找到相应的TreeViewItem。更糟糕的是,在以编程方式取消选择某个项目后,我无法通过单击进行重新选择。 – Anteru 2009-01-30 13:46:45

5

在设置TreeViewItem.IsSelected之后,可以通过在TreeView上调用Focus来解决无法选择的问题。

6

我发现这对我来说效果更好。我检查了对于我来说,如果它来自treeviewitem的originalsource将是一个图像或文本块。我也使用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; 
      } 
     } 
    } 
2

我实现了一次通用选择控件,并且需要这种行为。

这是怎么了我的方法看起来(适用于树视图):

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(); 
} 

基本上,从源头上走了树。如果找不到TreeViewItem,则用户单击空白空间。

4

可以有两个问题:

  1. TreeView所绑定所以的SelectedItem是绑定的集合的一个项目。
  2. 有许多水平,这样ItemContainerGenerator不包含最深层次的对象

这一切的原因,我使用这个功能,但是选择一定不会触发任何事件。

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; 
    } 
    } 
} 
1

使用下面

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; 
    } 
} 

扩展类然后在树视图的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(); 
    } 

希望它为你工作。我让它以这种方式工作......

1

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

完整的解释可以在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。这适用于2级嵌套儿童。希望它能为你工作。

对于持久性的缘故:

的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; 
} 
0

对于您使用treeview.Select一个C#树视图edNode = null;我不确定这是否适用于WPF。

相关问题