c# - 如何使用 ItemsSource 和 DataTemplates 从数据对象呈现功能区

标签 c# wpf binding

我试图为我的功能区提供数据模板。

功能区声明如下,并附有一个 ItemTemplate。

<r:Ribbon Name="RibbonMain"
          ItemTemplate="{StaticResource HomeRibbonTabTemplate}">
</r:Ribbon>

数据模板如下:
<Window.Resources>
    <DataTemplate DataType="{x:Type local:RibbonContainer}" 
                  x:Key="HomeRibbonTabTemplate">
        <r:RibbonTab Header="{Binding Path=HeaderName}">
            <r:RibbonGroup Header="{Binding Path=GroupName}">
            </r:RibbonGroup>
        </r:RibbonTab>
    </DataTemplate>
</Window.Resources>

然后我附上 ItemsSource:
    public MainWindow()
    {
        InitializeComponent();

        var RibbonTabData = new ObservableCollection<RibbonContainer>();
        RibbonTabData.Add(new RibbonContainer("HeaderName", "GroupName"));
        RibbonMain.ItemsSource = RibbonTabData;
    }

最后是类:(仅包含两个字符串字段)
class RibbonContainer
{
    public string HeaderName
    {
        get;
        set;
    }

    public string GroupName
    {
        get;
        set;
    }

    public RibbonContainer(string _headername, string _groupname)
    {
        HeaderName = _headername;
        GroupName = _groupname;
    }
}

在选项卡标题中显示完全限定的类名,我得到了不起眼的结果,而且功能区组也没有显示。 (这就是数据模板应该解决的问题?)
该怎么办?

最好的祝福

最佳答案

我不完全确定从哪里开始,但也许有一个简短的警告,在尝试创建 RibbonControl完全来自数据Binding和数据项,你真的是在为自己打开一大 jar 的屁屁。这是因为为其设计代码的开发人员对其中的一些使用了非常规的模式,并且未能充分记录如何使用它来做事。通过在本网站上搜索可以找到一些最佳资源。

因此,无论如何,如果您准备进行痛苦的艰苦斗争,请继续阅读。您的第一个错误是尝试使用 DataTemplate对于RibbonTab因为它是扩展 System.Windows.Controls.ItemsControl 因此需要 HierarchicalDataTemplate .您的第二个错误是声明 RibbonTab在模板中,正如@devhedgehog 在评论中提到的那样。

您的第三个错误是设置 x:Key DataTemplate 的值(value)并将其应用于 Ribbon.ItemsTemplate属性(property)...我知道,我知道...如果这不是 RibbonControl,这是一件很明智的事情。 .您必须向那些开发人员询问为什么这不起作用,但您最好接受它不起作用并调整您的代码。您只需删除 x:Key值和 Ribbon.ItemsTemplate属性并让框架隐式应用模板。

现在,如果您想要多个 RibbonGroup ,那么您的第四个错误是在 RibbonTab 的模板中定义它。 .如果您要正确执行此操作,那么您的数据类将需要匹配 Ribbon 中的各个级别的 UI 元素。 .我的意思是你需要创建一个 RibbonGroupData也上课。该类需要 RibbonButtonData 的集合为每个 RibbonButton 提供数据的对象在用户界面中。所以你应该得到这样的结果:

public class RibbonTabData : BaseDataType
{
    private string name = string.Empty;
    private ObservableCollection<RibbonGroupData> ribbonGroupData = new ObservableCollection<RibbonGroupData>();

    public string Name
    {
        get { return name; }
        set { name = value; NotifyPropertyChanged("Name"); }
    }

    public ObservableCollection<RibbonGroupData> RibbonGroupData
    {
        get { return ribbonGroupData; }
        set { ribbonGroupData = value; NotifyPropertyChanged("RibbonGroupData"); }
    }
}

public class RibbonGroupData : BaseDataType
{
    private string name = string.Empty;
    private ObservableCollection<RibbonButtonData> ribbonButtonData = new ObservableCollection<RibbonButtonData>();

    public string Name
    {
        get { return name; }
        set { name = value; NotifyPropertyChanged("Name"); }
    }

    public ObservableCollection<RibbonButtonData> RibbonButtonData
    {
        get { return ribbonButtonData; }
        set { ribbonButtonData = value; NotifyPropertyChanged("RibbonButtonData"); }
    }
}

public class RibbonButtonData : BaseDataType
{
    private string name = string.Empty;

    public string Name
    {
        get { return name; }
        set { name = value; NotifyPropertyChanged("Name"); }
    }
}
BaseDataType类只实现 INotifyPropertyChanged界面。当然,您需要为 ICommand 添加额外的属性。 s 和图像源等。您甚至可能需要不同的 RibbonButtonData不同类型的RibbonButton 具有不同属性的类s 然后你需要一个通用的 RibbonButtonBaseData它们都扩展的类,因此您的集合可以包含所有不同的类型。因此,您还有很多工作要做,但鉴于此示例代码,您可以在 Ribbon 中显示它。像这样:
<Ribbon:RibbonWindow.Resources>
    <HierarchicalDataTemplate DataType="{x:Type DataTypes:RibbonTabData}" 
        ItemsSource="{Binding RibbonGroupData}">
        <TextBlock Text="{Binding Name}" />
    </HierarchicalDataTemplate>
    <DataTemplate DataType="{x:Type DataTypes:RibbonButtonData}">
        <Ribbon:RibbonButton Label="{Binding Name}" 
            LargeImageSource="/WpfRibbonApplication1;component/Images/LargeIcon.png" />
    </DataTemplate>
    <HierarchicalDataTemplate DataType="{x:Type DataTypes:RibbonGroupData}" 
        ItemsSource="{Binding RibbonButtonData}">
        <Ribbon:RibbonGroup Header="{Binding Name}" />
    </HierarchicalDataTemplate>
</Ribbon:RibbonWindow.Resources>
<Ribbon:Ribbon x:Name="Ribbon" ItemsSource="{Binding RibbonTabData}" />

现在在设置为 DataContext 的 View 模型中对于Window ,我可以添加一些虚拟数据来测试它是否正常工作:
RibbonTabData.Add(new RibbonTabData() { Name = "Tab 1", RibbonGroupData = new ObservableCollection<RibbonGroupData>() { new RibbonGroupData() { Name = "Group 1", RibbonButtonData = new ObservableCollection<RibbonButtonData>() { new RibbonButtonData() { Name = "Button 1" }, new RibbonButtonData() { Name = "Button 2" }, new RibbonButtonData() { Name = "Button 3" } } }, new RibbonGroupData() { Name = "Group 2", RibbonButtonData = new ObservableCollection<RibbonButtonData>() { new RibbonButtonData() { Name = "Button 1" }, new RibbonButtonData() { Name = "Button 2" } } } } });
RibbonTabData.Add(new RibbonTabData() { Name = "Tab 2" });
RibbonTabData.Add(new RibbonTabData() { Name = "Tab 3" });

我们得到了这个:

enter image description here

然而,即使有了这个有益的开始,您仍然有很多工作要做。

关于c# - 如何使用 ItemsSource 和 DataTemplates 从数据对象呈现功能区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21966941/

相关文章:

C# 任务未按预期工作。奇怪的错误

c# - 在 try-finally block 中等待

WPF - 将许多图像一张一张地加载到 ObservableCollection 中

c# - WPF:DoubleAnimation "To"属性绑定(bind)计时

forms - Vue.js 单向绑定(bind)表单

cocoa - 如何将 NSMutableString 绑定(bind)到 NSTextView 的值?

c# - 如何在C#中成功下载一个.exe文件?

c# - 什么时候使用 yield ?

c# - 如何获取 WPF Webbrowser 控件的屏幕截图?

c# - 标记扩展的奇怪行为。它在设计模式下不起作用吗?