MVVM功能区应用程序菜单实现(WPF 4.5功能区)

时间:2013-12-23 19:02:24

标签: c# wpf mvvm ribbon

我正在尝试使用MVVM模式在WPF 4.5中实现功能区控件的应用程序菜单。因此,我创建了一个ApplicationMenuViewModel,它包含一个可观察的AbstractApplicationMenuItemViewModel集合,它是一个用于统一类的抽象类...... SplitItem和... Item。 SplitItem应该能够包含其他RibbonApplicationMenuSplitItems或者只是简单的RibbonApplicationMenuItems到任意级别的层次结构。因此它包含一个ObservableCollection,它可能包含...... SplitItems或plain ... Items。 由于其他架构原因,ApplicationMenu本身是通过工厂类提供的。我现在遇到的问题是ApplicationMenu中根本没有显示任何内容。 ViewModel是正确实例化的,所以我认为问题主要是由于我对ApplicationMenuSplitItemViewModel和ApplicationMenuViewModel中可能包含的两个不同项的抽象。 那么问题是实现模板和/或样式以使RibbonApplicationMenu显示的最灵活,可维护和简单的方法是什么? 目前应用以下模板:

<!--Ribbon Application Menu Styling and Templating-->
<DataTemplate DataType="{x:Type rvmmnu:ApplicationMenuViewModel}">
    <RibbonApplicationMenu ItemsSource="{Binding Children}"/>
</DataTemplate>

<DataTemplate DataType="{x:Type rvmmnu:ApplicationMenuItemViewModel}">
    <RibbonApplicationMenuItem Header="{Binding DisplayName}" 
                               ImageSource="{Binding ImageSource}" 
                               Command="{Binding Command}"/>
</DataTemplate>

<DataTemplate DataType="{x:Type rvmmnu:ApplicationMenuSplitItemViewModel}">
    <RibbonApplicationSplitMenuItem ItemsSource="{Binding Children}"
                                    Header="{Binding DisplayName}"/>
</DataTemplate>

功能区本身使用此XAML实例化:

    <Ribbon DockPanel.Dock="Top" ItemContainerStyle="{StaticResource    ResourceKey=ribbonTabStyle}" 
            ItemsSource="{Binding Path=Ribbon.Tabs}" 
            ApplicationMenu="{Binding Path=Ribbon.ApplicationMenu}"/>

使用此配置,应用程序菜单此刻不显示任何内容。我想这个问题源于我正在抽象出菜单中包含的两个分层项之间的差异。我正在考虑为RibbonApplicationMenu和RibbonApplicationMenuSplitItem使用自定义模板选择器。我想到的另一种方法是将不同的对象类型(... SplitItem和... Item)分成两个不同的集合,并对ItemsSource属性使用多重绑定。但我对这些方法并不满意,因为我认为有一种更简单的方法来实现我想要的目标。

1 个答案:

答案 0 :(得分:1)

我最终通过使用模板和样式选择器来检查提供给功能区的对象类型并返回通过XAML实例提供的模板来实现整个过程。现在的XAML如下:

    <!--Ribbon Application Menu Styling and Templating-->

<Style x:Key="appMnuItemStyle">
    <Setter Property="RibbonApplicationMenuItem.Header" Value="{Binding DisplayName}"/>
    <Setter Property="RibbonApplicationMenuItem.ImageSource" Value="{Binding ImageSource}"/>
    <Setter Property="RibbonApplicationMenuItem.Command" Value="{Binding Command}"/>
</Style>

<Style x:Key="appMnuSplitItemStyle">
    <Setter Property="RibbonApplicationSplitMenuItem.ItemsSource" Value="{Binding Children}"/>
    <Setter Property="RibbonApplicationSplitMenuItem.Header" Value="{Binding DisplayName}"/>
    <Setter Property="RibbonApplicationSplitMenuItem.ItemTemplateSelector" Value="{DynamicResource appMnuItemTemplateSelector}"/>
    <Setter Property="RibbonApplicationSplitMenuItem.ImageSource" Value="{Binding Image}"/>
</Style>

<HierarchicalDataTemplate x:Key="appMnuSplitItemTemplate" DataType="{x:Type rvmmnu:ApplicationMenuSplitItemViewModel}"
                          ItemsSource="{Binding Children}"
                          ItemContainerStyle="{StaticResource ResourceKey=appMnuSplitItemStyle}"/>


<DataTemplate x:Key="appMnuItemTemplate"/>


<rvmmnu:ApplicationMenuItemTemplateSelector x:Key="appMnuItemTemplateSelector" 
                                            PlainItemTemplate="{StaticResource ResourceKey=appMnuItemTemplate}" 
                                            SplitItemTemplate="{StaticResource ResourceKey=appMnuSplitItemTemplate}"/>

<rvmmnu:ApplicationMenuStyleSelector x:Key="appMnuItemStyleSelector"
                                     PlainItemStyle="{StaticResource ResourceKey=appMnuItemStyle}" 
                                     SplitItemStyle="{StaticResource ResourceKey=appMnuSplitItemStyle}"/>

功能区现在实例化如下:

        <Ribbon DockPanel.Dock="Top" ItemContainerStyle="{StaticResource ResourceKey=ribbonTabStyle}" 
            ItemsSource="{Binding Path=Tabs}" DataContext="{Binding Ribbon}">
        <Ribbon.ApplicationMenu>
            <RibbonApplicationMenu ItemsSource="{Binding ApplicationMenu.Children}"
                                   ItemTemplateSelector="{StaticResource ResourceKey=appMnuItemTemplateSelector}"
                                   ItemContainerStyleSelector="{StaticResource appMnuItemStyleSelector}"/>
        </Ribbon.ApplicationMenu>
    </Ribbon>

我不确定这是否是最佳解决方案。但它对我有用。