2010-02-21 74 views
7

我使用MVVM將視圖綁定到樹中的對象。我有一個實現在我的樹中的項目一個基類和基類有一個ContextMenu屬性:使用MVVM,ContextMenu ViewModel如何找到打開ContextMenu的ViewModel?

public IEnumerable<IMenuItem> ContextMenu 
    { 
     get 
     { 
      return m_ContextMenu; 
     } 
     protected set 
     { 
      if (m_ContextMenu != value) 
      { 
       m_ContextMenu = value; 
       NotifyPropertyChanged(m_ContextMenuArgs); 
      } 
     } 
    } 
    private IEnumerable<IMenuItem> m_ContextMenu = null; 
    static readonly PropertyChangedEventArgs m_ContextMenuArgs = 
     NotifyPropertyChangedHelper.CreateArgs<AbstractSolutionItem>(o => o.ContextMenu); 

結合基類(和所有派生類)實現了結合到一個文本菜單的查看屬性:

<ContextMenu x:Name="contextMenu" ItemsSource="{Binding Path=(local:AbstractSolutionItem.ContextMenu)}" 
      IsEnabled="{Binding Path=(local:AbstractSolutionItem.ContextMenuEnabled)}" 
      ItemContainerStyle="{StaticResource contextMenuStyle}"/> 

在菜單中的每一項被綁定到一個IMenuItem對象(一個ViewModel所述菜單項)。當你點擊菜單項時,它使用命令在基礎對象上執行命令。這一切都很好。

但是,一旦命令在IMenuItem類上執行,它有時需要獲取用戶右鍵單擊的對象的引用,以調出上下文菜單(或至少該對象的ViewModel)。這是上下文菜單的整點。我應該如何將樹項目ViewModel的引用傳遞給MenuItem ViewModel?請注意,一些上下文菜單由樹中的許多對象共享。

回答

4

我通過處理父控件上的ContextMenuOpening事件(在View中擁有ContextMenu的事件)解決了這個問題。我還向IMenuItem添加了一個Context屬性。處理程序如下所示:

private void stackPanel_ContextMenuOpening(
     object sender, ContextMenuEventArgs e) 
    { 
     StackPanel sp = sender as StackPanel; 
     if (sp != null) 
     { 
      // solutionItem is the "context" 
      ISolutionItem solutionItem = 
       sp.DataContext as ISolutionItem; 
      if (solutionItem != null) 
      { 
       IEnumerable<IMenuItem> items = 
        solutionItem.ContextMenu as IEnumerable<IMenuItem>; 
       if (items != null) 
       { 
        foreach (IMenuItem item in items) 
        { 
         // will automatically set all 
         // child menu items' context as well 
         item.Context = solutionItem; 
        } 
       } 
       else 
       { 
        e.Handled = true; 
       } 
      } 
      else 
      { 
       e.Handled = true; 
      } 
     } 
     else 
     { 
      e.Handled = true; 
     } 
    } 

這利用了一次只能打開一個ContextMenu的事實。

10

ContextMenu對象上有一個名爲「PlacementTarget」的DP - 將設置爲上下文菜單所附帶的UI元素 - 您甚至可以將它用作綁定源,因此您可以將它傳遞給您的命令通過CommandParameter:

http://msdn.microsoft.com/en-us/library/system.windows.controls.contextmenu.placementtarget.aspx

編輯:你的情況,你會希望PlacementTarget的虛擬機,所以你會結合可能看起來更像:

{Binding Path=PlacementTarget.DataContext, RelativeSource={RelativeSource Self}} 
+0

-1來源不能如果指定使用RelativeSource。運行時異常。 – 2012-03-20 18:18:34

+0

DataContext =「{Binding PlacementTarget.DataContext,RelativeSource = {RelativeSource Self}}」 – JoanComasFdz 2012-04-17 09:05:54