简体   繁体   English

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

[英]MVVM Ribbon Application Menu Implementation (WPF 4.5 Ribbon)

I am trying to Implement the Application Menu of a Ribbon Control in WPF 4.5 using the MVVM Pattern. 我正在尝试使用MVVM模式在WPF 4.5中实现功能区控件的应用程序菜单。 Therefore I created an ApplicationMenuViewModel which contains an observable collection of AbstractApplicationMenuItemViewModel which is an abstract class used to unify the classes ...SplitItem and ...Item. 因此,我创建了一个ApplicationMenuViewModel,其中包含一个可观察的AbstractApplicationMenuItemViewModel集合,该集合是用于统一类... SplitItem和... Item的抽象类。 The SplitItem shall be able to contain other RibbonApplicationMenuSplitItems or just plain RibbonApplicationMenuItems to an arbitrary level of hierarchy. SplitItem应该能够包含其他RibbonApplicationMenuSplitItems或仅包含简单的RibbonApplicationMenuItems到任意级别的层次结构。 Therefore it contains itself an ObservableCollection which may contain ...SplitItems or plain ...Items. 因此,它本身包含一个ObservableCollection,其中可能包含... SplitItems或普通... Items。 The ApplicationMenu itself is provided through a Factory Class due to other Architectural Reasons. 由于其他架构原因,ApplicationMenu本身通过工厂类提供。 The problem I am experiencing now is that nothing is shown in the ApplicationMenu at all. 我现在遇到的问题是ApplicationMenu中什么都没有显示。 The ViewModel is instantiated correctly so I think that the problem is mainly due to my abstraction of the two different items that may be contained inside ApplicationMenuSplitItemViewModel and ApplicationMenuViewModel. ViewModel已正确实例化,因此我认为问题主要是由于我对ApplicationMenuSplitItemViewModel和ApplicationMenuViewModel中可能包含的两个不同项目的抽象。 So the question is what is the most flexible, maintainable and easy way to implement the templating and/or styling to get the RibbonApplicationMenu to show up? 因此,问题是实现模板和/或样式以显示RibbonApplicationMenu的最灵活,可维护和最简单的方法是什么? At the moment the following template is applied: 目前,已应用以下模板:

<!--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>

The Ribbon itself is instantiated with this XAML: 功能区本身是用以下XAML实例化的:

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

With this configuration the Application Menu shows nothing at the moment. 使用此配置,“应用程序菜单”目前不显示任何内容。 I suppose the problem is steming from the fact that I am abstracting away the difference between the two hierarchical items contained in the menu. 我想问题出在我提取菜单中包含的两个层次项之间的差异这一事实。 I was thinking about using a custom template selector for RibbonApplicationMenu and RibbonApplicationMenuSplitItem. 我正在考虑为RibbonApplicationMenu和RibbonApplicationMenuSplitItem使用自定义模板选择器。 Another approach I was thinking about was to divide the different object types (...SplitItem and ...Item) into two different collections and use a multi binding for the ItemsSource Property. 我正在考虑的另一种方法是将不同的对象类型(... SplitItem和... Item)划分为两个不同的集合,并对ItemsSource属性使用多重绑定。 But I am not really satisfied with these approaches because I think that there is an easier way to achieve what I want. 但是我对这些方法并不真正满意,因为我认为有一种更简单的方法可以实现我想要的。

I finally implemented the whole thing by using a Template and a Style Selector checking the type of the object provided to the ribbon and returning the templates provided via the XAML instantiation. 我最终通过使用模板和样式选择器检查提供给功能区的对象的类型并返回通过XAML实例提供的模板来实现了整个过程。 The XAML for this is now the follow: 现在的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}"/>

The Ribbon is now instantiated like this: 功能区现在被实例化为:

        <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>

I am not really sure if this is the best solution. 我不确定这是否是最佳解决方案。 But it works for me. 但这对我有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM