C# 如何使用ItemsSource和DataTemplates从数据对象渲染功能区
我试图为我的功能区提供一个数据模板 功能区声明如下,并附加了ItemTemplateC# 如何使用ItemsSource和DataTemplates从数据对象渲染功能区,c#,wpf,binding,C#,Wpf,Binding,我试图为我的功能区提供一个数据模板 功能区声明如下,并附加了ItemTemplate <r:Ribbon Name="RibbonMain" ItemTemplate="{StaticResource HomeRibbonTabTemplate}"> </r:Ribbon> 在选项卡标题中显示完全限定的类名,而ribbongroup也没有显示,这一结果并不令人印象深刻。这就是datatemplate应该解决的问题? 怎么办 致以最诚挚的问候我不太确定
<r:Ribbon Name="RibbonMain"
ItemTemplate="{StaticResource HomeRibbonTabTemplate}">
</r:Ribbon>
在选项卡标题中显示完全限定的类名,而ribbongroup也没有显示,这一结果并不令人印象深刻。这就是datatemplate应该解决的问题?
怎么办
致以最诚挚的问候我不太确定从何处开始,但也许有一个简短的警告,在尝试完全从数据绑定和数据项创建RibbonControl时,您真的是在给自己开一个巨大的玩笑。这是因为为其设计代码的开发人员对其中一些代码使用了非常规模式,并且未能充分记录如何使用它。一些最好的资源将通过在本网站上搜索找到 所以,不管怎样,如果你正在经历一场痛苦的、艰难的斗争,请继续读下去。您的第一个错误是尝试为RibbonTab使用DataTemplate,因为它是扩展的,因此需要一个。您的第二个错误是在模板中声明RibbonTab,正如@devhedgehog在评论中提到的那样 第三个错误是为DataTemplate设置x:Key值并将其应用于Ribbon.ItemsTemplate属性。。。我知道,我知道。。。如果这不是RibbonControl,那么这是一件非常明智的事情。您将不得不询问那些开发人员为什么这不起作用,但您最好接受它不起作用,并修改您的代码。您只需要删除x:Key值和Ribbon.ItemsTemplate属性,并让框架隐式应用模板 现在,如果您想要多个RibbonGroup,那么您的第四个错误是在RibbonTab的模板中定义它。如果要正确执行此操作,那么您的数据类将需要匹配功能区中不同级别的UI元素。我的意思是,您也需要创建一个RibbonGroupData类。该类需要一组RibbonButton数据对象,这些对象将数据提供给UI中的每个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"); }
}
}
<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的视图模型中,我可以添加一些虚拟数据来测试它是否正常工作:
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" });
我们得到这个:
然而,即使有了这个有用的开始,您仍然有很多工作要做。我不确定从哪里开始,但可能有一个简短的警告,即在尝试完全从数据绑定和数据项创建RibbonControl时,您真的是在给自己开一个巨大的玩笑。这是因为为其设计代码的开发人员对其中一些代码使用了非常规模式,并且未能充分记录如何使用它。一些最好的资源将通过在本网站上搜索找到 所以,不管怎样,如果你正在经历一场痛苦的、艰难的斗争,请继续读下去。您的第一个错误是尝试为RibbonTab使用DataTemplate,因为它是扩展的,因此需要一个。您的第二个错误是在模板中声明RibbonTab,正如@devhedgehog在评论中提到的那样 第三个错误是为DataTemplate设置x:Key值并将其应用于Ribbon.ItemsTemplate属性。。。我知道,我知道。。。如果这不是RibbonControl,那么这是一件非常明智的事情。您将不得不询问那些开发人员为什么这不起作用,但您最好接受它不起作用,并修改您的代码。您只需要删除x:Key值和Ribbon.ItemsTemplate属性,并让框架隐式应用模板 现在,如果您想要多个RibbonGroup,那么您的第四个错误是在RibbonTab的模板中定义它。如果要正确执行此操作,那么您的数据类将需要匹配功能区中不同级别的UI元素。我的意思是,您也需要创建一个RibbonGroupData类。该类需要一组RibbonButton数据对象,这些对象将数据提供给UI中的每个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"); }
}
}
<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的视图模型中,我可以添加一些虚拟数据来测试它是否正常工作:
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" });
我们得到这个:
然而,即使有了这个有用的开始,你仍然有很多工作要做。通过阅读谢里登的答案,我成功地创造了以下结果: 可以将事件处理程序附加到所需控件的不同控件 如何使用ribbonbutton处理事件示例 当然,使用数据绑定将标记属性附加到ribbonbutton模板 将加载的事件附加到ribbonbutton模板中 创建字典:在windowname.xaml.cs中
public Dictionary<string, List<RoutedEventHandler>> EventLibrary = new Dictionary<string, List<RoutedEventHandler>>();
将事件添加到字典,并使用事件类型扩展字符串
EventLibrary.Add("NAME_RIBBONBUTTON_CLICKEVENT", new List<RoutedEventHandler> { new RoutedEventHandler(RibbonButton_Test)});
这是事件加载的代码:
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<RoutedEventHandler> value = EventLibrary[cmd.Tag.ToString() + "_CLICKEVENT"];
for (int i = 0; i < value.Count; i++)
{
cmd.AddHandler(RibbonButton.ClickEvent, value[i]);
}
}
}
通过阅读Sheridans的答案,我成功地得出了以下结果: 不同的控制 ols具有将事件处理程序附加到所需控件的可能性 如何使用ribbonbutton处理事件示例 当然,使用数据绑定将标记属性附加到ribbonbutton模板 将加载的事件附加到ribbonbutton模板中 创建字典:在windowname.xaml.cs中
public Dictionary<string, List<RoutedEventHandler>> EventLibrary = new Dictionary<string, List<RoutedEventHandler>>();
将事件添加到字典,并使用事件类型扩展字符串
EventLibrary.Add("NAME_RIBBONBUTTON_CLICKEVENT", new List<RoutedEventHandler> { new RoutedEventHandler(RibbonButton_Test)});
这是事件加载的代码:
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<RoutedEventHandler> value = EventLibrary[cmd.Tag.ToString() + "_CLICKEVENT"];
for (int i = 0; i < value.Count; i++)
{
cmd.AddHandler(RibbonButton.ClickEvent, value[i]);
}
}
}
这里是一个WPF博客,您可以在这里下载解决方案,在这里您可以找到一些有用的东西:
所有功能区控件的ViewModels
具有所有适当绑定的样式
因此,在使用上述内容的最后,我收到了更简单的解决方案:
<HierarchicalDataTemplate DataType="{x:Type ribbonVM:RibbonTabVM}" ItemsSource="{Binding Groups}">
<RibbonTab DataContext="{Binding}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type ribbonVM:RibbonGroupVM}" ItemsSource="{Binding Controls}">
<RibbonGroup DataContext="{Binding}" />
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type ribbonVM:RibbonButtonVM}">
<RibbonButton DataContext="{Binding}" />
</DataTemplate>
我向VMs中添加的唯一内容是子元素的集合。这里是一个在WPF中的博客,您可以在那里下载解决方案,在那里您可以找到一些有用的内容:
所有功能区控件的ViewModels
具有所有适当绑定的样式
因此,在使用上述内容的最后,我收到了更简单的解决方案:
<HierarchicalDataTemplate DataType="{x:Type ribbonVM:RibbonTabVM}" ItemsSource="{Binding Groups}">
<RibbonTab DataContext="{Binding}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type ribbonVM:RibbonGroupVM}" ItemsSource="{Binding Controls}">
<RibbonGroup DataContext="{Binding}" />
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type ribbonVM:RibbonButtonVM}">
<RibbonButton DataContext="{Binding}" />
</DataTemplate>
我向VMs添加的唯一内容是子元素的集合。Hmm据我所知,您将容器列表设置为Ribbon控件的项源。这将自动导致Ribbon为您创建RibbonTabs。此外,您还希望为每个RibbonTab模板设置特定的格式。但问题是您定义了另一个RibbonTab,它将放置在第一个自动创建的RibbonTab中。因此,你的应用程序开始表现得很奇怪。嗯,据我所知,你设置了一个容器列表作为功能区控件的项源。这将自动导致Ribbon为您创建RibbonTabs。此外,您还希望为每个RibbonTab模板设置特定的格式。但问题是您定义了另一个RibbonTab,它将放置在第一个自动创建的RibbonTab中。因此,你的应用程序开始表现得很奇怪。我最大的感谢!我成功地动态添加了不同的控件。见下面的答案,我不得不赞扬你在WPF方面的专业知识和技能。你是一个天才,现在添加事件和一切都很容易!我最大的感谢!我成功地动态添加了不同的控件。见下面的答案,我不得不赞扬你在WPF方面的专业知识和技能。你是一个天才,现在添加事件和一切都很容易!