2013-12-23 58 views
0

我想在WPF 4.5中使用MVVM模式實現功能區控件的應用程序菜單。因此,我創建了一個ApplicationMenuViewModel,其中包含AbstractApplicationMenuItemViewModel的可觀察集合,該集合是用於統一類的抽象類... SplitItem和... Item。 SplitItem應該能夠包含其他RibbonApplicationMenuSplitItems或僅包含RibbonApplicationMenuItems的任意級別的層次結構。因此它包含一個ObservableCollection,它可能包含... SplitItems或普通... Items。 由於其他架構原因,ApplicationMenu本身是通過工廠類提供的。我現在遇到的問題是ApplicationMenu中根本沒有顯示任何內容。 ViewModel實例化正確,所以我認爲這個問題主要是由於我抽象了ApplicationMenuSplitItemViewModel和ApplicationMenuViewModel中可能包含的兩個不同項目。 所以問題是什麼是最靈活,可維護和簡單的方式來實現模板和/或樣式來使RibbonApplicationMenu顯示? 目前下面的模板應用:MVVM功能區應用程序菜單實現(WPF 4.5功能區)

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

我最終通過使用模板和樣式選擇器檢查提供給功能區的對象的類型並返回通過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> 

我真的不知道這是否是最好的解決辦法。但它適用於我。

+0

嗨,不知道你是否會看到這個。我偶然發現了你的代碼,我正試圖學習如何將viewModels綁定到功能區。你是否可以共享代碼(下載)以便我可以看到並學習謝謝 – developer9969