MVVM is a well-known foundation for flexible and well-structured applications for such platforms as WinUI and WPF. That’s why we pay special attention to MVVM usage scenarios when developing our suite of controls. In this blog post, we will show you how to use the
WinUI Data Grid with some basic MVVM scenarios.
Create a View Model and Bind the Data Grid to Data
Let's start with a simple view model that contains data for the Data Grid.
This example uses a
compile-time generated view model to keep its code compact and clean. Install the
DevExpress.Mvvm.CodeGenerators
NuGet package to obtain access to view model generators.
Create a view model with the
Source property that retrieves data from the data model and can be used as the
GridControl's binding source:
using DevExpress.Mvvm.CodeGenerators;
// ...
[GenerateViewModel]
public partial class MainViewModel {
public MainViewModel() {
Source = ProductsDataModel.GetProducts();
}
[GenerateProperty]
ObservableCollection<Product> source;
}
In the Window class, create a ViewModel property that returns the created view model. This property allows you to use the x:Bind technique to bind the Data Grid to view model properties. The x:Bind is a relatively new markup extension that uses type information at compile-time to optimize the binding.
public sealed partial class MainWindow : Window {
public MainViewModel ViewModel { get; } = new MainViewModel();
public MainWindow() {
this.InitializeComponent();
}
}
Bind the Data Grid's
ItemsSource property to the
Source collection of the view model:
<Window
x:Class="WinUIMVVMGrid.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WinUIMVVMGrid"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:dxg="using:DevExpress.WinUI.Grid"
mc:Ignorable="d">
<Grid>
<dxg:GridControl ItemsSource="{x:Bind ViewModel.Source}"/>
</Grid>
</Window>

Generate Data Grid Columns from your View Model
The Data Grid offers flexible APIs to generate and configure columns according to the MVVM pattern. This technique allows you to change the set of grid columns dynamically, based on the data source type or other custom logic in your view model.
Create classes that describe grid columns. In this example, we use columns that display text values, a column with the
ComboBox editor, and a column that displays DateTime values:
using DevExpress.Mvvm;
// ...
public class TextColumn : BindableBase {
public TextColumn(string fieldname) {
FieldName = fieldname;
}
public string FieldName { get; }
}
public class ComboBoxColumn : TextColumn {
public ComboBoxColumn(string fieldname, IList items) : base(fieldname) {
Items = items;
}
public IList Items { get; }
}
public class DateColumn : TextColumn {
public DateColumn(string fieldname) : base(fieldname) { }
}
Add the Columns collection to the view model and populate it with grid columns you want to display:
[GenerateViewModel]
public partial class MainViewModel {
public MainViewModel() {
Source = ProductsDataModel.GetProducts();
IList Countries = Source.Select(x => x.Country).Distinct().ToList();
Columns = new ObservableCollection<TextColumn>() {
new TextColumn(nameof(Product.ProductName)),
new ComboBoxColumn(nameof(Product.Country), Countries),
new TextColumn(nameof(Product.UnitPrice)),
new DateColumn(nameof(Product.OrderDate))
};
}
[GenerateProperty]
ObservableCollection<Product> source;
[GenerateProperty]
ObservableCollection<TextColumn> columns;
}
The Data Grid generates its columns based on templates. Specify a template for each column type and create a template selector that returns a column template based on a column type:
xmlns:dx="using:DevExpress.WinUI.Core"
<Grid.Resources>
<dx:TypedDataTemplateSelector x:Name="ColumnTemplateSelector">
<DataTemplate x:DataType="local:TextColumn" x:Name="TextColumn">
<dxg:GridTextColumn FieldName="{x:Bind FieldName}"/>
</DataTemplate>
<DataTemplate x:DataType="local:ComboBoxColumn" x:Name="ComboBoxColumn">
<dxg:GridComboBoxColumn FieldName="{x:Bind FieldName}" ItemsSource="{x:Bind Items}"/>
</DataTemplate>
<DataTemplate x:DataType="local:DateColumn" x:Name="DateColumn">
<dxg:GridDateColumn FieldName="{x:Bind FieldName}"/>
</DataTemplate>
</dx:TypedDataTemplateSelector>
</Grid.Resources>
In the code snippet above, we use
TypedDataTemplateSelector, which allows you to choose templates without writing a single line of C# code. You can specify a standard template selector instead.
<dxg:GridControl ItemsSource="{x:Bind ViewModel.Source}"
NavigationStyle="Cell"
ColumnsSource="{x:Bind ViewModel.Columns}"
ColumnTemplateSelector="{StaticResource ColumnTemplateSelector}"/>

Obtain Selected Items in your View Model
The Data Grid allows you to bind the collection of its selected items to a property in your view model.
Add a collection for selected items to the view model and initialize it in the view model's constructor. You can also modify this collection, and the Data Grid will reflect such changes:
[GenerateViewModel]
public partial class MainViewModel {
public MainViewModel() {
Source = ProductsDataModel.GetProducts();
// ...
Selection = new ObservableCollection<Product>() {Source.ElementAt(0)};
}
// ...
[GenerateProperty]
ObservableCollection<Product> selection;
}
<dxg:GridControl ...
SelectionMode="RowExtended"
SelectedItems="{x:Bind ViewModel.Selection, Mode=TwoWay}"/>
This is all you need to do to synchronize the Data Grid's selected items with a view model property.
Use UI Services to Invoke a Message Box from your View Model
Now we'll describe how to show a message box with the selected rows according to the MVVM technique. In this case, we'll use our
UI Services to avoid accessing visual elements from the view model.
<dxg:GridControl ...
SelectionMode="RowExtended"
SelectedItems="{x:Bind ViewModel.Selection, Mode=TwoWay}">
<dx:Interaction.Behaviors>
<dx:MessageBoxService ServiceClient="{x:Bind ViewModel}"/>
</dx:Interaction.Behaviors>
</dxg:GridControl>
[GenerateViewModel(ImplementISupportUIServices=true)]
public partial class MainViewModel {
// ...
IMessageBoxService MessageBoxService => GetUIService<IMessageBoxService>();
[GenerateCommand]
async void ShowSelectedRows() {
string Text = "";
foreach (Product product in Selection) {
Text += product.ProductName + "\r\n";
}
await MessageBoxService.ShowAsync(Text, "Selected Products");
}
bool CanShowSelectedRows() => Selection.Any();
}
Subscribe to the
Selection collection's
CollectionChanged event to refresh the
ShowSelectedRows command's
CanExecute state each time a user selects or unselects a row:
[GenerateViewModel(ImplementISupportUIServices=true)]
public partial class MainViewModel {
public MainViewModel() {
// ...
Selection.CollectionChanged += (s, e) => ShowSelectedRowsCommand.RaiseCanExecuteChanged();
}
// ...
}
Add a button that executes the ShowSelectedRows command:
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="35"/>
</Grid.RowDefinitions>
<!-- ... -->
<Button Grid.Row="1"
HorizontalAlignment="Stretch"
Content="Show Selected Products"
Command="{x:Bind ViewModel.ShowSelectedRowsCommand}"/>
</Grid>


Use the EventToCommand Behavior to Assign Data Grid events to View Model Commands
The Data Grid allows you to use the
EventToCommand behavior to associate Data Grid events with the view model commands. You can use this behavior to initialize a new row in the view model.
<dxg:GridControl ...
NewItemRowPosition="Top">
<dx:Interaction.Behaviors>
<dx:EventToCommand EventName="AddingNewRow"
PassEventArgsToCommand="True"
Command="{x:Bind ViewModel.AddingNewRowCommand}"/>
</dx:Interaction.Behaviors>
</dxg:GridControl>
Create a command that adds a new object with predefined values to the data source when a user starts to edit the
New Item Row:
[GenerateCommand]
void AddingNewRow(AddingNewEventArgs e) =>
e.NewObject = new Product {ProductName = "", Country = "Austria", UnitPrice = 0, OrderDate = System.DateTime.Today};

Recap
In this post, we have described how to use our MVVM techniques with the WinUI Data Grid. You have learned how to:
- Bind the Data Grid's ItemsSource property to a collection in a view model.
- Specify grid columns in a view model and display them in the Data Grid.
- Access the Data Grid's selected items from the view model.
- Convert the Data Grid's events to commands in a view model.
Note that v22.1 also offers new great features for the WinUI Data Grid. See
What’s New for complete information.
Free DevExpress Products – Get Your Copy Today
The following free DevExpress product offers remain available. Should you have any questions about the free offers below, please submit a ticket via the
DevExpress Support Center at your convenience. We’ll be happy to follow-up.