【问题标题】:WPF data binding of a Ribbon control功能区控件的 WPF 数据绑定
【发布时间】:2013-04-11 13:45:27
【问题描述】:

我有一个工作动态菜单,它是数据绑定到由应用程序动态控制的分层项目集合。以下是 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 Ribbon 控件呈现这个底层菜单结构,最初使用 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,但将 RibbonTab 的样式应用于 RibbonGroup 时出现错误。

另一个相关问题是:如果 AppAction 对象具有功能区控件样式鉴别器属性(即 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 AppActionCollection: ObservableCollection<AppAction>
{
}

可以通过以下方式创建示例菜单树:

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);
    }
}

【问题讨论】:

  • 你为什么使用ResourcesDataTemplate?你想做什么?
  • 我正在使用资源,因为据说 HierarchicalDataTemplate 在不使用资源的情况下无法使用嵌套级别。以此类推,资源都是剩饭剩菜。第二个 sn-p 不起作用(还)。

标签: wpf data-binding ribbon


【解决方案1】:

抱歉耽搁了,我正在寻找解决您问题的方法,但很遗憾我没有找到。 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;
    }
}

在 MainWindow.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>

结果:

希望对你有所帮助。

我尽力了。

【讨论】:

  • 感谢您的回复,您的示例使用绑定到功能区的单个对象(“MyDate”)。我有一个“AppAction”类型对象的嵌套树,每个对象都具有带有(可能)更多子 AppAction 对象的 Items 属性,并且嵌套项目的级别应该绑定到 RibbonTab、RibbonGroup 和 RibbonButton。
  • 能否请您编辑您的问题以在代码后面添加您的类逻辑和窗口,我真的不明白您是否有类或一个对象的列表。
  • 非常感谢您的解决方案,它以非常简洁的方式解决了问题。
  • @MoHaKa,你的回答也解决了我的问题。你知道为什么this 不起作用吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-22
  • 1970-01-01
  • 2015-07-07
相关资源
最近更新 更多