【问题标题】:How do I bind a Ribbon control to my ViewModel?如何将 Ribbon 控件绑定到我的 ViewModel?
【发布时间】:2011-11-03 11:11:39
【问题描述】:

从昨天开始,我一直在努力使用 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>

以及它呈现的内容:

如您所见,“静态”选项卡运行良好,功能区组(“管理员”)的“标题”显示在正确的位置。

现在,“传统人工智能”标签,没有按钮(每组应该有 2 个按钮),并且 RibbonGroup 标题显示有趣(低于它们应该在的位置)。

如果您对我在这里做错了什么有任何线索,请告诉我 :) 我对 WPF 世界很陌生,所以我显然不能正确理解模板...

帮助您拨打电话的一些事实: - 模型加载正确,因为我们可以看到“组 1”和“组 2”,它们是在 ViewModel 中加载的假数据的一部分 - 我试过 Telerik 的 RadRibbon,它的行为完全一样!所以除非他们在同一个地方都错了,否则问题一定来自我

晚安,祝你好运:)

【问题讨论】:

  • 您需要做的第一件事是打开数据绑定的调试消息:i.stack.imgur.com/MF8i5.png 接下来,重新运行并检查输出窗口,看看有什么错误。
  • @Will:期待看到你的回答。
  • @Den:对不起,我不能像以前那样回答了。你知道,我必须花很少的时间来处理旗帜。如果您想知道为什么不鼓励在其他网站上发布完整的解决方案,我建议您在 Meta Stack Overflow 上询问。

标签: wpf mvvm viewmodel ribbon caliburn.micro


【解决方案1】:

我也在 MVVM 应用程序中使用功能区,并决定坚持使用 XAML 中定义的控件,将它们链接到我的视图模型层中定义的类中的静态 ICommand 属性。这非常不灵活,但到目前为止对我有用。

如果你已经下载并安装了官方的 Microsoft Ribbon,你会发现它的源代码和一些示例在:

C:\Program Files\Microsoft 功能区 WPF\MicrosoftRibbonForWPFSourceAndSamples

这包括一个同样实现 MVVM 的示例。这使用了一种完全不同的方法,尽管可能不是您需要的,但我认为查看它可能会有所帮助。

【讨论】:

    【解决方案2】:

    我昨天遇到了同样的问题,并且很努力地寻找解决方案。

    我认为您的问题可以通过 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>
    

    【讨论】:

    • 你可以提供一些关于HierarchicalDataTemplate的参考
    • HierarchicalDataTemplate 在 WPF 中很常见,但何时使用它们并不明显,这就是我首先回答问题的原因;)
    【解决方案3】:

    这里是死灵海报队长:

    我遇到了同样的渲染问题,这是我的解决方案

                <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,我能够检查活树并在那里找到问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-13
      • 1970-01-01
      • 2012-08-15
      • 2021-04-20
      • 2020-03-06
      相关资源
      最近更新 更多