There is a set of classes (unknown at compile time) that provide a set of commands, and a view model that contains a collection of these classes. Need to show a set of commands in the RibbonGroup on the tape.

I imagine it like this. I declare my classes that implement some empty interface:

 public ClassA : ISomeClass { public ICommand Command1 { get; } public ICommand Command2 { get; } } public ClassB : ISomeClass { public ICommand Command3 { get; } } 

We declare the main window view model, which contains a list of the classes declared above:

 public MainVm { public ISomeClass[] SomeClasses { get; } public MainVm() { SomeClasses = new[] { new ClassA(), new ClassB() }; } } 

I use resource dictionaries to represent helper classes:

 // представление ClassA <ResourceDictionary ...> <RibbonButton x:Key="Command1_ItemKey" Label="Command1" Command="{Binding Command1}" /> <RibbonButton x:Key="Command2_ItemKey" Label="Command2" Command="{Binding Command2}" /> </ResourceDictionary> // представление ClassB <ResourceDictionary ...> <RibbonButton x:Key="Command3_ItemKey" Label="Command3" Command="{Binding Command3}" /> </ResourceDictionary> 

The presentation part for the main presentation model:

 <RibbonTab Header="Home"> <RibbonGroup Header="Main" ItemsSource="{Binding SomeClasses}"> // вот здесь непонятно, что делать. Нужно каким-то образом связать каждый конкретный элемент со списком кнопок в представлении </RibbonGroup> </RibbonTab> 

I can get a collection of buttons from a resource dictionary associated with a specific auxiliary class. I do not understand how it can be inserted into the RibbonGroup .

  • Hm In theory, you should not put controls in the dictionary, only styles / templates / whatever. Because the control cannot have two Parents. - VladD 4:34 pm

1 answer 1

You say that you have a ResourceDictionary attached to each class. This in theory solves the problem.

Put the following in ResourceDictionary :

 // представление ClassA <ResourceDictionary ...> <DataTemplate DataType="{x:Type vm:ClassA}"> <!-- без ключа! --> <StackPanel Orientation="Horizontal"> <RibbonButton Label="Command1" Command="{Binding Command1}" /> <RibbonButton Label="Command2" Command="{Binding Command2}" /> </StackPanel> </DataTemplate> </ResourceDictionary> 

Thus, the ResourceDictionary declared a View for this VM class ClassA .

Now, this presentation should be used in ribbon. For this you have several options. If for VM data this is the only view you need, add all these ResourceDictionary as MergedDictionary to Application.Resources in runtime. If these VMs have another view, collect all the ResourceDictionary and add them to the specific RibbonTab 's resources.

Next, your code should just be like this:

 <RibbonGroup Header="Main" ItemsSource="{Binding SomeClasses}"/> 

The mapping of your classes will come from ResourceDictionary .

Look like that's it.

  • Thank. It really works. I tried to add buttons to the template, but did not guess to put them in the StackPanel. - Vlad
  • one
    @Vlad: The main trick is the DataTemplate , which establishes how the ContentPresenter will display this VM type. - VladD
  • @Vlad: Please! Glad that helped. - VladD
  • I did that first. But in the template you can not just take and put two controls. I did not think of putting them in a container. - Vlad