如何使用ItemsSource和DataTemplates从数据对象呈现function区

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

function区声明如下,并附加了ItemTemplate。

  

Datatemplate如下:

         

然后我附上ItemsSource:

  public MainWindow() { InitializeComponent(); var RibbonTabData = new ObservableCollection(); 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; } } 

我得到了在标题标题中显示完全限定类名的不起眼的结果,并且ribbongroup也没有显示。 (这是datatemplate应解决的问题?)怎么办?

最好的祝福

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

所以无论如何,如果你想要一场痛苦的,艰难的斗争,请继续阅读。 您的第一个错误是尝试将DataTemplate用于RibbonTab因为它扩展了System.Windows.Controls.ItemsControl ,因此需要HierarchicalDataTemplate 。 你的第二个错误是在模板中声明了RibbonTab ,正如评论中提到的@devhedgehog。

你的第三个错误是为你的DataTemplate设置x:Key值并将其应用到Ribbon.ItemsTemplate属性……我知道,我知道…… 如果这不是RibbonControl那么这是一个明智的做法。 你不得不问那些开发人员为什么不起作用,但你最好只是接受它没有并调整你的代码。 您只需要删除x:Key值和Ribbon.ItemsTemplate属性,并让Framework 隐式应用模板。

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

 public class RibbonTabData : BaseDataType { private string name = string.Empty; private ObservableCollection ribbonGroupData = new ObservableCollection(); public string Name { get { return name; } set { name = value; NotifyPropertyChanged("Name"); } } public ObservableCollection RibbonGroupData { get { return ribbonGroupData; } set { ribbonGroupData = value; NotifyPropertyChanged("RibbonGroupData"); } } } public class RibbonGroupData : BaseDataType { private string name = string.Empty; private ObservableCollection ribbonButtonData = new ObservableCollection(); public string Name { get { return name; } set { name = value; NotifyPropertyChanged("Name"); } } public ObservableCollection 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和图像源等添加额外的属性。您甚至可能需要具有不同类型的RibbonButton的不同属性的不同RibbonButtonData类,然后您需要一个共同的RibbonButtonBaseData类,它们都扩展了,因此您的collections可以包含所有不同类型。 所以你还有很多事要做,但是给定这个示例代码,你可以在Ribbon显示它,如下所示:

             

现在在设置为WindowDataContext的视图模型中,我可以添加一些虚拟数据来测试它是否全部工作:

 RibbonTabData.Add(new RibbonTabData() { Name = "Tab 1", RibbonGroupData = new ObservableCollection() { new RibbonGroupData() { Name = "Group 1", RibbonButtonData = new ObservableCollection() { new RibbonButtonData() { Name = "Button 1" }, new RibbonButtonData() { Name = "Button 2" }, new RibbonButtonData() { Name = "Button 3" } } }, new RibbonGroupData() { Name = "Group 2", RibbonButtonData = new ObservableCollection() { new RibbonButtonData() { Name = "Button 1" }, new RibbonButtonData() { Name = "Button 2" } } } } }); RibbonTabData.Add(new RibbonTabData() { Name = "Tab 2" }); RibbonTabData.Add(new RibbonTabData() { Name = "Tab 3" }); 

我们得到这个:

在此处输入图像描述

然而,即使有了这个有用的开始,你还有很多工作要做。

通过阅读Sheridans的回答,我设法创建了以下结果:

在此处输入图像描述

(可以将事件处理程序附加到所需控件的不同控件)。

我是如何进行事件处理的(例如使用ribbonbutton)

  1. 将标签属性附加到您的ribbonbutton模板(当然使用数据绑定)
  2. 将加载的事件附加到function区按钮模板中
  3. 创建一个字典:(在你的windowname.xaml.cs中

     public Dictionary> EventLibrary = new Dictionary>(); 
  4. 将事件添加到字典并使用事件类型扩展字符串

     EventLibrary.Add("NAME_RIBBONBUTTON_CLICKEVENT", new List { new RoutedEventHandler(RibbonButton_Test)}); 
  5. 这是加载事件的代码:

      private void RibbonButton_Loaded(object sender, EventArgs e) { System.Windows.Controls.Ribbon.RibbonButton cmd = (System.Windows.Controls.Ribbon.RibbonButton)sender; if (EventLibrary.ContainsKey(cmd.Tag.ToString() + "_CLICKEVENT")) { List value = EventLibrary[cmd.Tag.ToString() + "_CLICKEVENT"]; for (int i = 0; i < value.Count; i++) { cmd.AddHandler(RibbonButton.ClickEvent, value[i]); } } } 

这是WPF博客中旧post的链接,在那里你可以下载存档与解决方案,在那里你可以找到几个有用的东西:

  • 所有function区控件的ViewModels
  • 具有所有适当绑定的样式

所以最后使用上面的东西我收到了更简单的解决方案:

          

我添加到VM的唯一内容是子元素的集合。