2010-02-21 43 views
2

我有一個視圖模型(AbstractContextMenu)代表我的上下文菜單(IContextMenu),我綁定一個真正的文本菜單將其與一個DataTemplate:我可以使用DataTemplate將ContextMenu應用於ContextMenuViewModel嗎?

<DataTemplate DataType="{x:Type local:AbstractContextMenu}"> 
    <ContextMenu x:Name="contextMenu" 
      ItemsSource="{Binding Path=(local:IContextMenu.Items)}" 
      IsEnabled="{Binding Path=(local:IContextMenu.IsEnabled)}"/> 
</DataTemplate> 

然後,我有一個虛擬ConcreteContextMenu進行測試,只是從AbstractContextMenu繼承。 AbstractContextMenu只是實現了這個接口:

public interface IContextMenu : IExtension 
{ 
    IEnumerable<IMenuItem> Items { get; set; } 
    bool IsEnabled { get; set; } 
} 

我用它作爲其他視圖模型對象的屬性:

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

然後我綁定一個StackPanel到視圖模型,並在StackPanel中ContextMenu屬性綁定到視圖模型的ContextMenu屬性:

<StackPanel Orientation="Horizontal" 
       ContextMenu="{Binding Path=(local:AbstractSolutionItem.ContextMenu)}" 
       ContextMenuOpening="stackPanel_ContextMenuOpening"> 
    <!-- stuff goes in here --> 
    </StackPanel> 

當我運行此,上的StackPanel中的ContextMenuOpening事件被激發,但文本菜單是NE顯示。我不確定我是否可以執行此操作(使用DataTemplate將ContextMenu應用於ContextMenu ViewModel)。有人知道嗎?

回答

1

AbstractSolutionItem.ContextMenu是什麼類型的?如果它對應於您的問題中的ContextMenu屬性,那麼問題可能是該類型錯誤。 FrameworkElementContextMenu財產預計實際ContextMenu,而不是IContextMenu。嘗試在調試應用程序時檢查輸出窗口 - 您可能會收到錯誤消息,指出這是問題所在。

而不是使用DataTemplate來定義ContextMenu的,只是把模板StackPanel.ContextMenu的內容:

<StackPanel Orientation="Horizontal" 
    ContextMenu="{Binding Path=(local:AbstractSolutionItem.ContextMenu)}" 
    ContextMenuOpening="stackPanel_ContextMenuOpening"> 
    <StackPanel.ContextMenu DataContext="{Binding Path=(local:AbstractSolutionItem.ContextMenu)}"> 
     <ContextMenu x:Name="contextMenu" 
      ItemsSource="{Binding Path=Items}" 
      IsEnabled="{Binding Path=IsEnabled}"/> 
    </StackPanel.ContextMenu> 
    <!-- stuff goes in here --> 
</StackPanel> 

這應該讓你最的方式存在。但是,由於ContextMenu不知道如何從IMenuItem創建MenuItem,所以仍然存在問題。要解決這個問題,請爲ContextMenu創建一個ItemTemplate,它將IMenuItem的成員綁定到`MenuItem。

+0

嗨安迪。 WPF可以識別我爲AbstractMenuItem定義的DataTemplate,它確實創建了菜單(畢竟是MVVM的核心),但正如你所說,似乎我不能將StackPanel.ContextMenu屬性綁定到一個隨機對象並讓WPF將我的DataTemplate應用到它。我希望有辦法解決這個問題,但看起來我的選擇是零。謝謝。太糟糕了 - 我試圖去完整的MVVM,但很難。 – 2010-02-27 04:30:41

+0

這並沒有真正解決我的問題,但由於看起來沒有解決方案,我想要做什麼,這是「正確的」。 ;) – 2010-02-28 13:47:54

0

您能否在DataTemplate中的ItemsSource屬性中使用語法?使用括號通常意味着附屬的財產。並且Items似乎不是由IContextMenu定義的附加屬性(因爲接口不能定義這樣的屬性)。

DataTemplate鏈接到類型爲AbstractContextMenu的對象,該對象具有名爲Items的屬性。因此,DataTemplate中可以簡單地引用這樣的:

<DataTemplate DataType="{x:Type local:AbstractContextMenu}"> 
    <ContextMenu x:Name="contextMenu" 
      ItemsSource="{Binding Path=Items)}" 
      IsEnabled="{Binding Path=IsEnabled}"/> 
</DataTemplate> 

如果AbstractSolutionItem類是StackPanel的虛擬機,你可以結合這樣的:

<StackPanel Orientation="Horizontal" 
      ContextMenu="{Binding Path=ContextMenu}" 
      ContextMenuOpening="stackPanel_ContextMenuOpening"> 
<!-- stuff goes in here --> 
</StackPanel> 

當然,DataTemplate中必須來自StackPanel的「可訪問」。

+0

您可能不熟悉這種綁定語法,但它與您所描述的完全相同,只是效率更高,因爲它可以在編譯時而不是運行時解析。我忘記了語法的名稱,但是我儘可能地將其轉換爲使用它,因爲使用MVVM,您會執行大量綁定和性能問題。 – 2010-02-28 02:23:44

0

將視圖的ContextMenu屬性(本場景中的StackPanel)綁定到ViewModel的ContextMenu屬性,併爲綁定提供一個IValueConverter,它將創建ContextMenu對象並將IContextMenu設置爲它的DataContext。