2010-07-21 60 views
0

我有我的應用程序需要處理TreeViewItem的PreviewMouseRightButtonDown事件的動態級別(TreeView項目使用Hierachical數據模板具有可綁定的richtextbox)的WPF treeview。從TreeView的WPF PreviewMouseRightButtonDown事件獲取正確的TreeView項目

當我用鼠標右鍵單擊基於節點的水平樹節點此事件被擊中多次(等於TreeView項的水平。我認爲這是因爲這個預覽事件的隧道性質)

人請幫助我確定正確的命中,給出我右鍵單擊的確切樹視圖項目?

回答

1

最簡單的方法是使用冒泡事件MouseRightButtonDown而不是隧道事件PreviewMouseRightButtonDown。您可以將路由事件標記爲已處理,方法是將EventArgs的Handled屬性設置爲true,這將停止調用進一步的事件處理程序。這樣,只有最深的TreeViewItem纔會收到該事件。

如果您不能使用預覽事件,另一種方法是使用EventArgs中的OriginalSource屬性來查找實際單擊的UI元素。這可能是您的RichTextBox,因此您將需要使用一種方法來查找TreeViewItem類型的可視祖先。有一個在http://www.wpftutorial.net/LogicalAndVisualTree.html一個方法來獲得一個給定類型的祖先的例子:

public static class VisualTreeHelperExtensions 
{ 
    public static T FindAncestor<T>(DependencyObject dependencyObject) 
     where T : class 
    { 
     DependencyObject target = dependencyObject; 
     do 
     { 
      target = VisualTreeHelper.GetParent(target); 
     } 
     while (target != null && !(target is T)); 
     return target as T; 
    } 
} 

所以,你可以調用((DependencyObject)e.OriginalSource).FindAncestor<TreeViewItem>()找到被點擊的樹型視圖。如果你這樣做,你應該將事件處理程序附加到TreeView本身而不是TreeViewItems。這將在任何TreeViewItem中捕獲點擊,因爲它們都在樹中,但它只會被稱爲一次。


編輯:正如您指出,該方法不一樣,如果目標是FrameworkContentElement上,因爲它不是一個Visual工作。你可以做這樣的事情,而不是:

public static class VisualTreeHelperExtensions 
{ 
    public static T FindAncestor<T>(object dependencyObject) 
     where T : DependencyObject 
    { 
     var target = (DependencyObject)dependencyObject; 
     do 
     { 
      var visualParent = target is Visual ? VisualTreeHelper.GetParent(target) : null; 
      if (visualParent != null) 
      { 
       target = visualParent; 
      } 
      else 
      { 
       var logicalParent = LogicalTreeHelper.GetParent(target); 
       if (logicalParent != null) 
       { 
        target = logicalParent; 
       } 
       else 
       { 
        return null; 
       } 
      } 
     } 
     while (!(target is T)); 
     return (T)target; 
    } 
} 

那麼你應該能夠做VisualTreeHelperExtensions.FindAncestor<TreeViewItem>(e.OriginalSource)從OriginalSource得到樹型視圖。

+0

感謝您的想法,但在我的情況下,我不得不使用預覽事件,因爲樹視圖項目具有模板的richtextbox,並且它不會觸發TreeViewItem的冒泡事件。 e.OriginalSource不是richtextbox它是richtextbox中的flowdocument或Run或其他元素(將根據我右鍵單擊的位置進行更改) – Niruka 2010-07-21 14:00:52

+0

@Niruka:對不起,我包含的方法沒有處理FrameworkContentElement象Run的對象。看到我更新的答案。 – Quartermeister 2010-07-21 15:40:06

+0

非常感謝。第二種方法奏效。我做了一個非常小的修改。該行目標=((FrameworkElement)目標).Parent;已更改爲 target = VisualTreeHelper.GetParent(target); 看起來像,在回顧TreeViewItem的方式,屬性((FrameworkElement)目標).Parent已經返回null,當我們擊中一個Border元素,但VisualTreeHelper.GetParent(目標);將返回正確的父母。這應該有一個合理的解釋,但我對WPF太新了。再次感謝。順便說一句,我不知道如何設置這個問題的狀態作爲回答抱歉。 – Niruka 2010-07-22 09:10:49