2009-01-29 133 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。

相關問題