从昨天开始,我一直在努力使用MVVM在WPF上构建一个(我认为)简单的功能区。 我在互联网上找到了很多链接(在Stack Overflow上),但没有一个能真正解决我的问题。
简而言之,我的问题是:我做错了,或者像我正在做的那样将Ribbon绑定到ViewModel根本不可能?
这是我的菜单模型:每个 MenuGroup 应呈现为 RibbonGroup , MenuGroup 包含的集合MenuItem 应该呈现为 RibbonButton (当然在它们各自的 RibbonGroup 中)。
using Caliburn.Micro;
namespace MyCompany.Poc.Wpf.Models
{
public class MenuGroup
{
public MenuGroup()
{
Items = new BindableCollection<MenuItem>();
}
public string Name { get; set; }
public IObservableCollection<MenuItem> Items { get; set; }
}
}
using System.Windows.Input;
namespace MyCompany.Poc.Wpf.Models
{
public class MenuItem
{
public MenuGroup Group { get; set; }
public string Name { get; set; }
public string Link { get; set; }
public ICommand OpenMenuUrl { get; set; }
}
}
我的ViewModel只包含那些MenuGroup的集合,用于XAML上的绑定:
public IObservableCollection<MenuGroup> LegacyMenuItems
{
get { return _legacyMenuItems; }
}
一旦虚拟机实例化,就会填充(当前)集合,并附带虚假数据):
var group1 = new MenuGroup();
group1.Name = "Group 1";
var group2 = new MenuGroup();
group2.Name = "Group 2";
group1.Items.Add(new MenuItem {Group = group1, Link = "http://www.google.co.uk", Name = "Link 1", OpenMenuUrl = OpenMenuUrl});
group1.Items.Add(new MenuItem {Group = group1, Link = "http://www.google.co.uk", Name = "Link 2", OpenMenuUrl = OpenMenuUrl});
group2.Items.Add(new MenuItem {Group = group2, Link = "http://www.google.co.uk", Name = "Link 3", OpenMenuUrl = OpenMenuUrl});
group2.Items.Add(new MenuItem {Group = group2, Link = "http://www.google.co.uk", Name = "Link 4", OpenMenuUrl = OpenMenuUrl});
LegacyMenuItems.Add(group1);
LegacyMenuItems.Add(group2);
现在是XAML:
<my:Ribbon DockPanel.Dock="Top">
<my:RibbonTab Header="Legacy A.I." ItemsSource="{Binding LegacyMenuItems}">
<my:RibbonTab.ItemTemplate>
<DataTemplate>
<my:RibbonGroup Header="{Binding Name}" ItemsSource="{Binding Items}">
<my:RibbonGroup.ItemTemplate>
<DataTemplate>
<my:RibbonButton Label="{Binding Name}" Command="{Binding OpenMenuUrl}" CommandParameter="{Binding Link}"></my:RibbonButton>
</DataTemplate>
</my:RibbonGroup.ItemTemplate>
</my:RibbonGroup>
</DataTemplate>
</my:RibbonTab.ItemTemplate>
</my:RibbonTab>
<my:RibbonTab Header="Static">
<my:RibbonGroup Name="Administration" Header="Admin">
<my:RibbonButton Label="Stuffs" Command="{Binding Path=OpenMenuUrl}" CommandParameter="http://www.mycompany.com/somelink"></my:RibbonButton>
<my:RibbonButton Label="Google" Command="{Binding Path=OpenMenuUrl}" CommandParameter="http://www.google.co.uk"></my:RibbonButton>
</my:RibbonGroup>
</my:RibbonTab>
</my:Ribbon>
它呈现的内容:
正如您所看到的,“静态”选项卡效果很好,功能区组(“管理员”)的“标题”显示在正确的位置。
现在,“Legacy A.I.”选项卡,没有按钮(每组中应该有2个按钮),并且RibbonGroup标题显示有趣(低于它们应该的位置)。
如果你对我在这里做错了什么线索,请告诉我:) 我是WPF世界的新手,所以我显然不明白正确的模板...
帮助您拨打电话的一些事实: - 正确加载模型,因为我们可以看到“组1”和“组2”,它们是ViewModel中加载的假数据的一部分 - 我试过Telerik的RadRibbon,它的表现完全一样!因此,除非他们在同一个地方错了,否则问题必须来自我
晚安,祝你好运:)。
答案 0 :(得分:1)
我也在MVVM应用程序中使用功能区,并决定坚持使用XAML中定义的控件将它们链接到我的viewmodel层中定义的类中的静态ICommand属性。这是非常不灵活的,但到目前为止对我有用。
如果你已经下载并安装了官方的Microsoft功能区,你会发现它的来源和一些样本:
C:\ Program Files \ Microsoft Ribbon for WPF \ MicrosoftRibbonForWPFSourceAndSamples
这包括一个也实现MVVM的示例。这使用了一种完全不同的方法,虽然可能不是你所需要的,但我认为查看它可能会有所帮助。
答案 1 :(得分:0)
昨天我遇到了同样的问题,并且很难找到解决方案。
我认为您的问题可以通过 HierarchicalDataTemplate 来解决。
<r:Ribbon>
<r:RibbonTab Header="Legacy A.I." ItemsSource="{Binding LegacyMenuItems}">
<r:RibbonTab.Style>
<Style TargetType="{x:Type r:RibbonTab}">
<Setter Property="ItemsSource" Value="{Binding LegacyMenuItems}" />
<Setter Property="ItemTemplate">
<Setter.Value>
<HierarchicalDataTemplate DataType = "{x:Type r:RibbonGroup}"
ItemsSource = "{Binding Items}" >
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
</Setter.Value>
</Setter>
</Style>
</r:RibbonTab.Style>
</r:RibbonTab>
</r:Ribbon>
答案 2 :(得分:0)
Necroposter上尉在这里:
我有同样的渲染问题,这是我的解决方案
<HierarchicalDataTemplate DataType="{x:Type navigation:RibbonTabViewModel}" ItemsSource="{Binding Path=Groups}">
<TextBlock Text="{Binding Path=Title}"></TextBlock>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type navigation:RibbonGroupViewModel}" ItemsSource="{Binding Path=Items}">
<TextBlock Text="{Binding Path=Title}" ></TextBlock>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type navigation:RibbonButtonViewModel}">
<RibbonButton Label="{Binding Path=Title}" Command="{Binding Path=ClickedCommand}" CommandParameter="{Binding Path=.}"></RibbonButton>
</DataTemplate>
首先,我有一个RibbonGroup作为我的RibbonGroupViewModel的模板内容。感谢最新的VS我能够检查实时树并找到问题。