2015-06-28 94 views
1

我有一個TreeView,其中顯示通過TreeViews HierarchicalDataTemplate.ItemsSource綁定的項目。 TreeView的上下文菜單根據選擇的項目而改變。菜單項取決於所選項目。這意味着:上下文菜單是完全動態構建的。爲此,我編寫了一個MenuItemModel類,它用作菜單項的業務對象。像這樣:WPF通過MVVM動態構建ContextMenu

public class MenuItemModel : ViewModelBase 
{ 
    public string Header { get; set; } 
    public string Icon { get; set; } 
    public ObservableCollection<MenuItemModel> ChildItems { get; set; } 
    public UiCommand Command { get; set; } 
} 

到目前爲止好。但現在我有兩個問題:

問題1如何在菜單中顯示分隔符?我有另一個課程SeparatorMenuItemModel,我打算用於分隔符。但在這種情況下,我的ContextMenu需要包含Separator而不是MenuItem。我怎樣才能做到這一點?

問題2我試圖使用DataTemplate來定製我的MenuItems的顯示方式。但是這不會改變菜單本身,只是內容部分。我不得不爲ControlTemplate這個,但我怎麼能讓我的菜單改變ControlTemplate我可以用DataTemplate做什麼?

回答

1

我找到了解決這兩個問題的方法。

第一:我創造了兩種風格。一個類型MenuItemModel,另一個用於類型SeparatorMenuItemModel

<Style x:Key="theMenuItemStyle" TargetType="{x:Type MenuItem}"> 
    ... 
</Style> 

<Style x:Key="theSeparatorStyle" TargetType="{x:Type MenuItem}"> 
    <Setter Property="Template"> 
    <Setter.Value> 
    <ControlTemplate> ... </ControlTemplate> 
    </Setter.Value> 
    </Setter> 
</Style> 

我使用的樣式也改變了我的控制模板(除了一些其他的東西,這並不重要)。

然後我使用了一個StyleSelector,它根據顯示的項目的類型選擇應用的樣式。就像這樣:

<TreeView.ContextMenu> 
    <ContextMenu ItemsSource="{Binding ContextMenuItemRoot.ChildItems}" 
       ItemContainerStyleSelector="{StaticResource MenuItemStyleSelector}" /> 
    </TreeView.ContextMenu> 

而且StyleSelector本身的定義是這樣的:

public class MenuItemStyleSelector : StyleSelector 
{ 
    public Style MenuItemStyle { get; set; } 
    public Style SeparatorStyle { get; set; } 

    public override Style SelectStyle(object item, DependencyObject container) 
    { 
    if (item is SeparatorMenuItemModel) 
     return SeparatorItemStyle; 
    return MenuItemStyle; 
    } 
} 
0

看起來像你在這裏使用經典的組合模式。就SeparatorMenuItemModel而言,如何將MenuItemModel和SeparatorMenuItemModel從通用的類或接口繼承,例如IMenuItemModel(或MenuItemModelBase)?然後,您可以使用

public ObservableCollection<IMenuItemModel> ChildItems {get; set;} 

包含兩者。

不確定我完全理解問題2,但重要的是要明白ControlTemplate 完全替換控件的可視化樹;基本上你能夠(並且必須)從頭開始完全重建控制。通常情況下,這是比你想要做的更多的工作。

+0

我 「SeparatorMenuItemModel」 從MenuItemModel派生。所以這不是問題。我正在討論如何根據數據類型使我的菜單顯示「MenuItem」或「Separator」。 對於ControlTemplate:是的,我知道。我只是想知道是否有某種「ControlTemplateSelector」機制可用。 – Hemisphera