Skip to main content
A newer version of this page is available. .

MVVM Support

  • 6 minutes to read

This topic demonstrates two approaches of using the MVVM pattern in DXBars, DXRibbon and GalleryControl.

Defining UI at View Level

This is the simplest approach, with which a UI is defined at the View level. UI element behavior is implemented by commands defined in a View Model.

Example

This example creates a simple UI consisting of a MainMenuControl with a button. A click on the button invokes the ShowTextCommand defined in a bound POCO View Model.

Imports System
Imports System.Collections.Generic
Imports System.Configuration
Imports System.Data
Imports System.Linq
Imports System.Threading.Tasks
Imports System.Windows

Namespace WpfApplication25
    ''' <summary>
    ''' Interaction logic for App.xaml
    ''' </summary>
    Partial Public Class App
        Inherits Application

    End Class
End Namespace

Defining UI at View Model Level

This is an advanced approach, with which a UI is defined in View Models. The View Models contain all necessary information required to render or populate a visual component(s) with data. WPF DevExpress controls provide the following properties to support this MVVM pattern implementation.

  • …(Item)Source - This property is used to bind a component/class to a data collection.
  • …(Item)Style - Allows you to customize styles of visual objects generated using templates. It also allows you to implement custom template selecting logic.
  • …(Item)Template - Templates are used to render underlying objects in a specific form.
  • …(Item)TemplateSelector - Template selectors allow you to choose templates based on custom logic.

Below is the list of these properties provided by specific WPF DevExpress Menu and Navigation controls.

Class

Property

ToolBarControlBase

ItemsSource

ItemTemplate

ItemTemplateSelector

ItemStyle

BarManager

BarsSource

BarTemplate

BarTemplateSelector

BarStyle

Bar, BarLinkContainerItem, BarSubItem, PopupMenu

ItemLinksSource

ItemTemplate

ItemStyle

ItemTemplateSelector

ApplicationMenu, RibbonPageGroup

ItemLinksSource

ItemTemplate

ItemStyle

ItemTemplateSelector

RibbonControl, RibbonStatusBarControl

CategoriesSource

CategoryTemplate

CategoryStyle

CategoryTemplateSelector

RibbonPageCategory

PagesSource

PageTemplate

PageTemplateSelector

PageStyle

RibbonPage

GroupsSource

GroupTemplate

GroupStyle

GroupTemplateSelector

GalleryControl

GroupsSource

GroupTemplate

GroupStyle

GroupTemplateSelector

GalleryItemGroup

ItemsSource

ItemTemplate

ItemStyle

ItemTemplateSelector

Note

When you define a DataTemplate, the DataTemplate’s root element must be a ContentControl with the required object (bar, bar item, ribbon page, etc.) as the content.

Implicit Data Templates

The …Template and …TemplateSelector properties support the direct assignment of Data Templates. You can also associate Data Templates with certain View Models implicitly. Define a DataTemplate object in resources and associate it with a specific View Model using the DataType property. The DataType property should specify the type of the target View Model. The implicit template association feature is demonstrated in the “Implicit Data Templates” demo shipped with the installation.

Examples

Example 1

This example demonstrates the advanced approach to implement MVVM support in an application using DXBars. A complete example can be found in the “MVVM Bars” demo shipped with the installation. This very same approach is applicable when designing applications with DXRibbon and GalleryControl. See the “MVVM Ribbon” demo to learn more.

This example shows how to populate bars in a BarManager and bar items from underlying collections. Assume there are two classes (View Models) that describe bars and bar items. The first class, MVVMBarViewModel, provides a Bars collection, whose elements (BarViewModel objects) describe individual bars.

public class MVVMBarViewModel {
    public virtual ObservableCollection<BarViewModel> Bars { get; set; }

    public MVVMBarViewModel() {
        Bars = new ObservableCollection<BarViewModel>();
        //...
    }
    //...
}

The second class, BarViewModel, contains a Commands collection, whose elements (BarButtonInfo) contain information to initialize bar items.

public class BarViewModel {
    public BarViewModel() {
        Name = "";
        Commands = new ObservableCollection<BarButtonInfo>();
    }
    public virtual string Name { get; set; }
    public virtual ObservableCollection<BarButtonInfo> Commands { get; set; }
}

The main window’s DataContext is set to the MVVMBarViewModel in XAML. This DataContext will be propagated to the window’s children, including a BarManager component.

DataContext="{dxmvvm:ViewModelSource Type=local:MVVMBarViewModel}"

Once the BarManager is ensured of receiving the proper DataContext, it can be populated with bars from the MVVMBarViewModel.Bars collection using data binding.

<local:BarsDemoModule.Resources>
    <DataTemplate x:Key="barTemplate">
        <ContentControl>
            <dxb:Bar Caption="{Binding Name}" ItemLinksSource="{Binding Commands}"/>
        </ContentControl>
    </DataTemplate>
</local:BarsDemoModule.Resources>

<dxdb:DemoModuleControl>
    <Grid>
        <dxb:BarManager BarsSource="{Binding Bars}" BarTemplate="{StaticResource barTemplate}" BarStyle="{StaticResource barStyle}"/>
    </Grid>
</dxdb:DemoModuleControl>

Here, the BarManager.BarsSource property is bound to the MVVMBarViewModel.Bars collection. The BarManager.BarTemplate property is set to a template that will visualize elements in theBarManager.BarsSource collection. The collection’s elements (BarViewModel objects) are automatically assigned to the DataTemplate’s DataContext, allowing for bar settings initialization with BarViewModel properties. Thus, the Bar.Caption property is bound to the BarViewModel.Name property and the Bar.ItemLinkSource property is bound to the BarViewModel.Commands property. Generally speaking, a DataTemplate’s DataContext is automatically set to an object being visualized by this template.

When defining a DataTemplate for a Bar, the DataTemplate’s root element must be ContentControl with a Bar object as the content.

It is also possible to define a style that will be automatically applied to each bar created from a template. For instance, in the markup below, a style defines an item template selector (an object that selects templates for bar items based on custom logic).

<local:CommandTemplateSelector x:Key="itemTemplateSelector" SubItemTemplate="{StaticResource subItemTemplate}" ItemTemplate="{StaticResource itemTemplate}"/>

<Style x:Key="barStyle" TargetType="dxb:Bar">
    <Setter Property="ItemTemplateSelector" Value="{StaticResource itemTemplateSelector}"/>
</Style>

<dxb:BarManager 
    ...
    BarStyle="{StaticResource barStyle}"
/>

All bindings between View Models and View classes are set up in XAML, without using code-behind files. However, there is one exception: template selectors must be written in code-behind files. The CommandTemplateSelector below chooses between two DataTemplates (SubItemTemplate or ItemTemplate).

public class CommandTemplateSelector : DataTemplateSelector {
    public DataTemplate SubItemTemplate { get; set; }
    public DataTemplate ItemTemplate { get; set; }
    public override DataTemplate SelectTemplate(object item, DependencyObject container) {
        if (item != null && item is BarButtonInfo) {
            if (item is GroupBarButtonInfo)
                return SubItemTemplate;
            else
                return ItemTemplate;
        }
        return null;
    }
}

The approach used to initialize bar items within bars is identical to the one used to initialize bars. See the “MVVM Bars” demo shipped with the installation for a complete example.

Example 2

Tip

A complete sample project is available in the DevExpress Code Examples database at http://www.devexpress.com/example=E5215.

The example demonstrates how to generate pages, groups and items from a collection according to the MVVM pattern. To generate pages in the RibbonPageCategory, bind the RibbonPageCategoryBase.PagesSource property to a collection. Use the RibbonPageCategoryBase.PageTemplate property to specify a template for generated pages.

The RibbonPage and RibbonPageGroup contain similar properties for generating groups and bar items:

See Also