绑定RibbonControl

时间:2016-09-22 16:14:12

标签: wpf devexpress ribbon-control

我正在使用DevExpress控件开发WPF应用程序,例如Ribbon控件。我希望能够动态地在功能区上放置按钮。我希望能够支持常规按钮和下拉按钮。

我在想类似下面的内容。

WPF查看:

<UserControl.Resources>
    <DataTemplate x:Key="RibbonCommandTemplate">
        <ContentControl>
            <dxb:BarButtonItem RibbonStyle="All" Content="{Binding Caption}"
                               Command="{Binding (dxr:RibbonControl.Ribbon).DataContext.MenuExecuteCommand,
                                         RelativeSource={RelativeSource Self}}" 
                               CommandParameter="{Binding}" />
        </ContentControl>
    </DataTemplate>
</UserControl.Resources>

<Grid>
    <DockPanel>
        <dxr:RibbonControl DockPanel.Dock="Top" RibbonStyle="Office2010">
            <dxr:RibbonDefaultPageCategory>
                <dxr:RibbonPage Caption="Home">
                    <dxr:RibbonPageGroup Caption="Dynamic Commands" 
                                         ItemLinksSource="{Binding DynamicCommands}"
                                         ItemTemplate="{StaticResource RibbonCommandTemplate}" />
                </dxr:RibbonPage>
            </dxr:RibbonDefaultPageCategory>
        </dxr:RibbonControl>
        <Grid/>
    </DockPanel>
</Grid>

查看型号:

public class RibbonCommand
{
    public string Caption { get; set; }
    public int CommandCode { get; set; }

    public ObservableCollection<RibbonCommand> SubItems { get; set; }

    public bool HasSubItems
    {
        get
        {
            if (SubItems != null)
                return (SubItems.Count > 0);
            else
                return false;
        }
    }
}

[POCOViewModel]
public class MainViewModel
{
    public ObservableCollection<RibbonCommand> DynamicCommands { get; set; }

    public MainViewModel()
    {
        DynamicCommands = new ObservableCollection<RibbonCommand>();

        // Regular buttons.
        DynamicCommands.Add(new RibbonCommand() { Caption = "Button 1", CommandCode = 1 });
        DynamicCommands.Add(new RibbonCommand() { Caption = "Button 2", CommandCode = 2 });

        // Drop-down button.
        RibbonCommand dropDownCommand = new RibbonCommand() { Caption = "Drop-Down", CommandCode = 3 };
        dropDownCommand.SubItems = new ObservableCollection<RibbonCommand>();
        dropDownCommand.SubItems.Add(new RibbonCommand() { Caption = "Sub-Item 1", CommandCode = 31 });
        dropDownCommand.SubItems.Add(new RibbonCommand() { Caption = "Sub-Item 2", CommandCode = 32 });
        dropDownCommand.SubItems.Add(new RibbonCommand() { Caption = "Sub-Item 3", CommandCode = 33 });
        DynamicCommands.Add(dropDownCommand);
    }

    public void MenuExecute(RibbonCommand command)
    {
        MessageBox.Show(string.Format("You clicked command with ID: {0} (\"{1}\").",
                        command.CommandCode, command.Caption), "Bound Ribbon Control");
    }
}

此代码使用我在DynamicCommands集合中添加的项目成功填充功能区,但我想支持SubItems集合中任何内容的项目的下拉按钮(上面示例中的第三个按钮)。

是否有办法有条件地更改DataTemplate中显示的控件类型。如果对象的HasSubItems为true,我想在条带上放置一个BarSubItem。如果它是假的,我将保留BarButtonItem。

2 个答案:

答案 0 :(得分:0)

如果这是常规WPF而不是UWP,并且子项的DataContexts属于不同类型,则可以在RibbonPageGroup的资源中定义多个具有DataTemplates属性的DataType(其中它们不会在任何不需要它们的范围内,并摆脱ItemTemplate属性:

<dxr:RibbonPageGroup 
    Caption="Dynamic Commands" 
    ItemLinksSource="{Binding DynamicCommands}">
    <dxr:RibbonPageGroup.Resources>
        <DataTemplate DataType="{x:Type local:RibbonCommand}">
            <!-- XAML stuff -->
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:SpecialRibbonCommand}">
            <!-- Totally different XAML stuff -->
        </DataTemplate>
    </dxr:RibbonPageGroup.Resources>

    <!-- etc -->

对于其他选项,您应该能够撰写DataTemplateSelector并将其提供给RibbonControl's ToolbarItemTemplateSelector propertyRibbonPageGroup's ItemTemplateSelector媒体资源。

最后,编写一个复杂的DataTemplate,其中多个子控件叠加在Grid中,以及一系列触发器,这些触发器仅根据DataContext的属性显示相应的一个。如果您只有两种不同的选项可以处理,这可能是最快捷,最简单的选择。

<DataTemplate x:Key="RibbonCommandTemplate">
    <Grid>
        <Label x:Name="OneThing" />
        <Label x:Name="AnotherThing" />
    </Grid>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding HasSubItems}" Value="True">
            <Setter TargetName="OneThing" Property="Visibility" Value="Collapsed" />
            <Setter TargetName="AnotherThing" Property="Visibility" Value="Visible" />
        </DataTrigger>
        <!-- Other triggers for HasSubItems == False, whatever -->
    </DataTemplate.Triggers>
</DataTemplate>

这看起来相当粗糙,但我在WPF中做了这么多,我已经对它感到厌恶了。

答案 1 :(得分:0)

我想出了一种使用DataTemplateSelector类的方法:

using System.Windows;
using System.Windows.Controls;
using RibbonDynamicButtons.ViewModels;

namespace RibbonDynamicButtons.Selectors
{
    public class RibbonCommandSelector : DataTemplateSelector
    {
        public DataTemplate CommandTemplate { get; set; }
        public DataTemplate SubCommandTemplate { get; set; }

        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            if(item is RibbonCommand)
            {
                RibbonCommand command = (RibbonCommand)item;
                if (command.HasSubItems)
                    return SubCommandTemplate; 
                else
                    return CommandTemplate;
            }

            return base.SelectTemplate(item, container);
        }
    }
}

我将我的选择器添加到xaml中,如下所示:

<UserControl
    ...
    xmlns:Selectors="clr-namespace:RibbonDynamicButtons.Selectors">
    <UserControlResources>
        <DataTemplate x:Key="RibbonSubItemTemplate">
            <ContentControl>
                <dxb:BarButtonItem RibbonStyle="SmallWithText" Content="{Binding Caption}"
                    Command="{Binding (dxr:RibbonControl.Ribbon).DataContext.MenuExecuteCommand,
                        RelativeSource={RelativeSource Self}}" CommandParameter="{Binding}" />
            </ContentControl>
        </DataTemplate>

        <Selectors:RibbonCommandSelector x:Key="RibbonCommandSelector">
            <Selectors:RibbonCommandSelector.CommandTemplate>
                <DataTemplate>
                    <ContentControl>
                        <dxb:BarButtonItem RibbonStyle="All"
                            Content="{Binding Caption}"
                            Command="{Binding (dxr:RibbonControl.Ribbon).DataContext.MenuExecuteCommand,
                                RelativeSource={RelativeSource Self}}" 
                            CommandParameter="{Binding}" />
                    </ContentControl>
                </DataTemplate>    
            </Selectors:RibbonCommandSelector.CommandTemplate>

            <Selectors:RibbonCommandSelector.SubCommandTemplate>
                <DataTemplate>
                    <ContentControl>
                        <dxb:BarSubItem RibbonStyle="All" Content="{Binding Caption}"
                            ItemLinksSource="{Binding SubItems}"
                            ItemTemplate="{StaticResource RibbonSubItemTemplate}" />
                    </ContentControl>
                </DataTemplate>
            </Selectors:RibbonCommandSelector.SubCommandTemplate>
        </Selectors:RibbonCommandSelector>
    </UserControlResources>

我将ItemTemplateSelector绑定到RibbonPageGroup上的选择器:

<dxr:RibbonPageGroup Caption="Dynamic Commands" ItemLinksSource="{Binding DynamicCommands}"
                     ItemTemplateSelector="{StaticResource RibbonCommandSelector}" />

我不需要对原始问题中包含的视图模型进行任何更改。

相关问题