开发者

How do I bind a Ribbon control to my ViewModel?

开发者 https://www.devze.com 2023-03-30 09:19 出处:网络
I\'ve been struggling since yesterday to build a (what I thought) simple Ribbon on WPF, using MVVM. I found quite a few links on the internet (and on Stack Overflow), but none could really solve my pr

I've been struggling since yesterday to build a (what I thought) simple Ribbon on WPF, using MVVM. I found quite a few links on the internet (and on Stack Overflow), but none could really solve my problem.

In a nutshell my question is: Am I doing it wrong, or is it just plain impossible to bind a Ribbon to a ViewModel like I'm doing?

In Details:

This is my model for the menu: Each MenuGroup should be rendered as a RibbonGroup, and MenuGroup contains a collection of MenuItem which should be rendered as a RibbonButton (inside their respective RibbonGroup of course).

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; }
    }
}

My ViewModel just contains a collection of those MenuGroup, for the binding on the XAML:

public IObservableCollection<MenuGroup> LegacyMenuItems
{
    get { return _legacyMenuItems; }
}

The collection is populated (for the time being) as soon as the VM is instanciated, with fake data):

var group1 = new MenuGroup();
group1.Name = "Group 1";开发者_JAVA技巧
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);

Now the 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>

And what it renders:

How do I bind a Ribbon control to my ViewModel?

How do I bind a Ribbon control to my ViewModel?

As you can see, the "Static" tab works well and the "title" for the ribbon group ("Admin") is displayed at the right place.

Now, the "Legacy A.I." tab, has no buttons (there should be 2 buttons in each group), and the RibbonGroup titles are displayed funny (below where they should be).

If you have any clue on what I'm doing wrong here, please tell me :) I'm very new on the WPF world, so I obviously don't understand templating properly...

A few facts to help you make a call: - The Model is loaded correctly, since we can see "Group 1" and "Group 2" which are part of the fake data loaded in the ViewModel - I tried Telerik's RadRibbon and it behaves exactly the same! So unless they are BOTH wrong at the same place, the problem must comes from me

Good night and good luck :)


I am using the ribbon also in a MVVM application and decided to stick with controls defined in XAML linking them to static ICommand properties in classes defined in my viewmodel layer. This is very inflexible but works for me so far.

If you have downloaded and installed the official Microsoft Ribbon you will find it's source and some sample's in:

C:\Program Files\Microsoft Ribbon for WPF\MicrosoftRibbonForWPFSourceAndSamples

This includes a sample that also implements MVVM. This uses a totally different method though an may not be what you need, but I think it may be helpful to look it over.


I had the same problem yesterday and struggled a lot to find a solution.

I think your problem could be solved with a 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>


Captain Necroposter here:

I had the same rendering issue and this is my solution

            <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>

To begin with i had a RibbonGroup as template content for my RibbonGroupViewModel. Thanks to latest VS i was able to inspect the live tree and find the issue there.

0

精彩评论

暂无评论...
验证码 换一张
取 消