2013-04-11 30 views
4

我有一个工作的动态菜单,它将数据绑定到由应用程序动态控制的项目的分层集合。对于低于参考是WPF声明:功能区控件的WPF数据绑定

 <Menu Grid.Row="1" Grid.ColumnSpan="2" ItemsSource="{Binding Actions}" Style="{StaticResource ResourceKey=dynamicMenu}"> 
     <Menu.Resources> 
      <HierarchicalDataTemplate DataType="{x:Type wm:AppAction}" ItemsSource="{Binding Path=Items}"> 
       <HierarchicalDataTemplate.ItemContainerStyle> 
        <Style TargetType="MenuItem"> 
         <Setter Property="IsCheckable" Value="{Binding IsCheckable}" /> 
         <Setter Property="IsChecked" Value="{Binding IsChecked}" /> 
         <Setter Property="Visibility" Value="{Binding Path=IsVisible, Converter={wc:BoolToCollapsedConverter}}"/> 
         <Setter Property="Command" Value="{Binding Command}" /> 
         <Setter Property="Icon" Value="{Binding Image}" /> 
         <Style.Triggers> 
          <DataTrigger Binding="{Binding Text}" Value=""> 
           <Setter Property="Template"> 
            <Setter.Value> 
             <ControlTemplate TargetType="{x:Type MenuItem}"> 
              <Separator HorizontalAlignment="Stretch" IsEnabled="False"/> 
             </ControlTemplate> 
            </Setter.Value> 
           </Setter> 
          </DataTrigger> 
         </Style.Triggers> 
        </Style> 
       </HierarchicalDataTemplate.ItemContainerStyle> 
       <StackPanel Orientation="Horizontal"> 
        <Image Source="{Binding ImageSource}" /> 
        <TextBlock Text="{Binding Text}" /> 
       </StackPanel> 
      </HierarchicalDataTemplate> 
     </Menu.Resources> 
    </Menu> 

现在我想使用Microsoft色带控制呈现此底层菜单结构,它使用RibbonTab和RibbonGroup为0级和RibbonButton为水平1(单组在每个最初构建标签)。

不幸的是,由于某些原因,它没有显示任何内容。这里是我到目前为止的声明:

 <r:Ribbon Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" x:Name="ribbon" Title="WPF Prototype App" ItemsSource="{Binding Actions}"> 
     <r:Ribbon.Resources> 
      <DataTemplate DataType="{x:Type wm:AppAction}"> 
       <r:RibbonTab Header="{Binding Text}"> 
        <r:RibbonGroup Header="{Binding Text}" ItemsSource="{Binding Actions}" Width="333"> 
         <r:RibbonGroup.Resources> 
          <DataTemplate DataType="{x:Type wm:AppAction}"> 
           <r:RibbonButton Label="{Binding Text}" LargeImageSource="{Binding ImageSource}"/> 
          </DataTemplate> 
         </r:RibbonGroup.Resources> 
        </r:RibbonGroup> 
       </r:RibbonTab> 
      </DataTemplate> 
     </r:Ribbon.Resources> 
    </r:Ribbon> 

我有一种感觉,这可能是一些简单的解决方法。 我尝试使用HierarchicalDataTemplate,但有关于应用于RibbonGroup的RibbonTab样式的错误。另一个相关的问题是:如果AppAction对象具有Ribbon控件样式的判别器属性(即ControlStyle [Tab,Group,Button,CheckBox,ComboBox]),根据值的动态创建适当的控件是多么容易?这个属性还是可能的?或者,对于复杂场景来说,只需在后续视图中定义功能区的一部分,并负责执行这些任务,并在视图可见时将其附加到它们中,这样做会更好吗

编辑:下面是AppAction类的简化版本的内容:

[ContentProperty("Items")] 
public class AppAction: PropertyChangedBase 
{ 
    public AppActionCollection Items { get; set; } 

    ICommand command; 
    public ICommand Command 
    { 
     get { return command; } 
     set { CheckSet(ref command, value); } 
    } 

    string text; 
    public string Text 
    { 
     get { return text; } 
     set { CheckSet(ref text, value); } 
    } 

    Uri imageSource; 
    public Uri ImageSource 
    { 
     get { return imageSource; } 
     set { image = null; CheckSet(ref imageSource, value); NotifyOfPropertyChange(() => Image); } 
    } 

    public AppAction() 
    { 
     Items = new AppActionCollection(); 
    } 
} 

AppActionCollection简化:

public class TestMenu 
{ 
    AppActionCollection menu = new AppActionCollection(); 

    public TestMenu() 
    { 
     var m = new AppAction { Text = "File" }; 
     m.Items.Add(new AppAction { Text = "Open" }); 
     m.Items.Add(new AppAction { Text = "Save" }); 
     m.Items.Add(new AppAction { Text = "" }); 
     m.Items.Add(new AppAction { Text = "Exit", Command = ApplicationCommands.Close }); 
     menu.Add(m); 

     m = new AppAction { Text = "Edit" }; 
     m.Items.Add(new AppAction { Text = "Copy" }); 
     m.Items.Add(new AppAction { Text = "Paste" }); 
     m.Items.Add(new AppAction { Text = "Cut" }); 
     m.Items.Add(new AppAction { Text = "Smile", Command = ApplicationCommands.Close }); 
     menu.Add(m); 
    } 
} 
+1

你为什么使用'Resources'和'DataTemplate'?你想做什么? – MoHaKa 2013-04-11 14:16:50

+0

我正在使用资源,因为假定HierarchicalDataTemplate不会使用嵌套级别而不使用资源。通过类比工作后,资源是一个剩余的。第二个代码段不起作用(还)。 – too 2013-04-11 14:29:18

回答

7

public class AppActionCollection: ObservableCollection<AppAction> 
{ 
} 

一个例子菜单树可以通过以下方式创建

对不起,我正在寻找解决您的问题,但不幸的是我没有找到。 HierarchicalDataTemplate不会帮助您,因为色带级别不是同一类型。

我认为解决您的问题的唯一方法是为每个级别制作新的DataTemplate。我知道这不是一个好的解决方案,但我认为这是唯一的方法。 如果你找到更好的方式,请分享你的知识并告诉我。

注意:在Menu的情况下,您可以使用HierarchicalDataTemplate,因为有一个类型MenuItem

编辑:

这是我达到:

MainWindow.xaml.cs:

public ObservableCollection<AppAction> child 
{ 
    get 
    { 
     ObservableCollection<AppAction> reVal = new ObservableCollection<AppAction>(); 
     reVal.Add(
      new AppAction() { Header = "File", Items = new ObservableCollection<AppAction>() { 
       new AppAction() { Header = "Font", Items = new ObservableCollection<AppAction>() { 
        new AppAction() { Header = "Arial" }, 
        new AppAction() { Header = "Segoe UI" }, 
        new AppAction() { Header = "Tahoma" } } }, 
       new AppAction() { Header = "Other", Items = new ObservableCollection<AppAction>() { 
        new AppAction() { Header = "Colse" } } } } }); 

     reVal.Add(
      new AppAction() { Header = "View", Items = new ObservableCollection<AppAction>() { 
       new AppAction() { Header = "A", Items = new ObservableCollection<AppAction>() { 
        new AppAction() { Header = "AButton" } } }, 
       new AppAction() { Header = "B", Items = new ObservableCollection<AppAction>() { 
        new AppAction() { Header = "BButton" } } }, 
       new AppAction() { Header = "C", Items = new ObservableCollection<AppAction>() { 
        new AppAction() { Header = "CButton" } } } } }); 
     return reVal; 
    } 
} 

并在主窗口。XAML:

<Window x:Class="rebbon.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525" Name="wind"> 

    <Window.Resources> 
     <DataTemplate x:Key="buttonTempl"> 
      <RibbonButton Label="{Binding Header}"/> 
     </DataTemplate> 
     <Style TargetType="RibbonGroup" x:Key="groupStyle"> 
      <Setter Property="Header" Value="{Binding Header}"/> 
      <Setter Property="ItemsSource" Value="{Binding Items}"/> 
      <Setter Property="ItemTemplate" Value="{StaticResource buttonTempl}"/> 
     </Style>   
     <Style TargetType="RibbonTab" x:Key="tabStyle"> 
      <Setter Property="Header" Value="{Binding Header}"/> 
      <Setter Property="ItemsSource" Value="{Binding Items}"/> 
      <Setter Property="ItemContainerStyle" Value="{StaticResource groupStyle}"/> 
     </Style> 
    </Window.Resources> 

    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="auto"/> 
      <RowDefinition Height="*"/> 
     </Grid.RowDefinitions> 

     <Ribbon ItemContainerStyle="{StaticResource tabStyle}" ItemsSource="{Binding ElementName=wind, Path=child}"/> 
    </Grid> 
</Window> 

结果:

enter image description here

我希望这会帮助你。

我尽了全力。

+0

感谢您的回复,您的示例使用了Ribbon绑定到的单个对象(“MyDate”)。我有一个类型为“AppAction”的对象的嵌套树,每个对象具有带有(可能)更多子AppAction对象的Items属性,嵌套项目的级别应绑定到RibbonTab,RibbonGroup和RibbonButton。 – too 2013-04-11 15:11:34

+0

请问你可以编辑你的问题来添加你的类逻辑和窗口后面的代码,我真的不明白,如果你有一个类或一个对象的列表。 – MoHaKa 2013-04-11 15:16:06

+0

当然,只是添加了C#代码,希望它有帮助。 – too 2013-04-11 15:33:59