How to: Bind the Grid to Columns and Summaries Specified in ViewModel
- 6 minutes to read
This example shows how to put columns and data summary definition logic in the ViewModel and setup the Grid Control.
Note
A complete sample project is available at https://github.com/DevExpress-Examples/how-to-bind-the-grid-to-columns-and-summaries-specified-in-viewmodel-e3358.
- MainWindow.xaml
- ColumnTemplateSelector.vb
- ViewModel.vb
- MainPage.xaml
- ViewModel.cs
- ColumnTemplateSelector.cs
<Window x:Class="WPFGridMVVMBindableColumns.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
xmlns:local="clr-namespace:SLGridMVVMBindableColumns"
Title="MainWindow" Height="600" Width="800">
<local:MainPage/>
</Window>
Imports System.Windows.Controls
Imports System.Windows
Imports Model
#If SILVERLIGHT Then
Imports DevExpress.Xpf.Core.Native
#End If
Namespace View
Public Class ColumnTemplateSelector
Inherits DataTemplateSelector
Public Overrides Function SelectTemplate(ByVal item As Object, ByVal container As DependencyObject) As DataTemplate
Dim column As Column = DirectCast(item, Column)
#If SILVERLIGHT Then
Return CType(LayoutHelper.FindParentObject(Of UserControl)(container).Resources(column.Settings & "ColumnTemplate"), DataTemplate)
#Else
Return DirectCast(CType(container, Control).FindResource(column.Settings & "ColumnTemplate"), DataTemplate)
#End If
End Function
End Class
End Namespace
Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.Collections.ObjectModel
Imports System.Reflection
Imports System.Xml.Serialization
Imports DevExpress.Data
Namespace Model
Public Class ViewModel
Private privateCities As List(Of String)
Public Property Cities() As List(Of String)
Get
Return privateCities
End Get
Private Set(ByVal value As List(Of String))
privateCities = value
End Set
End Property
Private privateSource As IList(Of Employee)
Public Property Source() As IList(Of Employee)
Get
Return privateSource
End Get
Private Set(ByVal value As IList(Of Employee))
privateSource = value
End Set
End Property
Private privateColumns As ObservableCollection(Of Column)
Public Property Columns() As ObservableCollection(Of Column)
Get
Return privateColumns
End Get
Private Set(ByVal value As ObservableCollection(Of Column))
privateColumns = value
End Set
End Property
Private privateTotalSummary As ObservableCollection(Of Summary)
Public Property TotalSummary() As ObservableCollection(Of Summary)
Get
Return privateTotalSummary
End Get
Private Set(ByVal value As ObservableCollection(Of Summary))
privateTotalSummary = value
End Set
End Property
Private privateGroupSummary As ObservableCollection(Of Summary)
Public Property GroupSummary() As ObservableCollection(Of Summary)
Get
Return privateGroupSummary
End Get
Private Set(ByVal value As ObservableCollection(Of Summary))
privateGroupSummary = value
End Set
End Property
Public Sub New()
Source = EmployeesData.DataSource
Dim cities_Renamed As New List(Of String)()
For Each employee As Employee In Source
If Not cities_Renamed.Contains(employee.City) Then
cities_Renamed.Add(employee.City)
End If
Next employee
Cities = cities_Renamed
Columns = New ObservableCollection(Of Column)() From { _
New Column() With {.FieldName="FirstName", .Settings = SettingsType.Default}, _
New Column() With {.FieldName="LastName", .Settings = SettingsType.Default}, _
New Column() With {.FieldName="BirthDate", .Settings = SettingsType.Default}, _
New ComboColumn() With {.FieldName="City", .Settings = SettingsType.Combo, .Source = Cities}, _
New Column() With {.FieldName="ImageData", .Settings = SettingsType.Image} _
}
TotalSummary = New ObservableCollection(Of Summary)() From { _
New Summary() With {.Type = SummaryItemType.Count, .FieldName = "FirstName"}, _
New Summary() With {.Type = SummaryItemType.Max, .FieldName = "BirthDate"} _
}
GroupSummary = New ObservableCollection(Of Summary)() From { _
New Summary() With {.Type = SummaryItemType.Count, .FieldName = "FirstName"} _
}
End Sub
End Class
Public Enum SettingsType
[Default]
Combo
Image
End Enum
Public Class Summary
Public Property Type() As SummaryItemType
Public Property FieldName() As String
End Class
Public Class Column
Public Property FieldName() As String
Public Property Settings() As SettingsType
End Class
Public Class ComboColumn
Inherits Column
Public Property Source() As IList
End Class
<XmlRoot("Employees")> _
Public Class EmployeesData
Inherits List(Of Employee)
Public Shared ReadOnly Property DataSource() As IList(Of Employee)
Get
Dim s As New XmlSerializer(GetType(EmployeesData))
#If SILVERLIGHT Then
Return DirectCast(s.Deserialize(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("SLGridMVVMBindableClumns.EmployeesWithPhoto.xml")), List(Of Employee))
#Else
Return DirectCast(s.Deserialize(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("WPFGridMVVMBindableColumns.EmployeesWithPhoto.xml")), List(Of Employee))
#End If
End Get
End Property
End Class
Public Class Employee
Public Property Id() As Integer
Public Property ParentId() As Integer
Public Property FirstName() As String
Public Property MiddleName() As String
Public Property LastName() As String
Public Property JobTitle() As String
Public Property Phone() As String
Public Property EmailAddress() As String
Public Property AddressLine1() As String
Public Property City() As String
Public Property StateProvinceName() As String
Public Property PostalCode() As String
Public Property CountryRegionName() As String
Public Property GroupName() As String
Public Property BirthDate() As Date
Public Property HireDate() As Date
Public Property Gender() As String
Public Property MaritalStatus() As String
Public Property Title() As String
Public Property ImageData() As Byte()
End Class
End Namespace
<UserControl
x:Class="SLGridMVVMBindableColumns.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:dxit="http://schemas.devexpress.com/winfx/2008/xaml/core/internal"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"
xmlns:model="clr-namespace:Model"
xmlns:view="clr-namespace:View">
<UserControl.DataContext>
<model:ViewModel/>
</UserControl.DataContext>
<UserControl.Resources>
<view:ColumnTemplateSelector x:Key="ColumnTemplateSelector"/>
<Style x:Key="ColumnStyle" TargetType="dxg:GridColumn">
<Setter Property="FilterPopupMode" Value="CheckedList"/>
</Style>
<DataTemplate x:Key="DefaultColumnTemplate">
<ContentControl>
<dxg:GridColumn FieldName="{Binding FieldName}"/>
</ContentControl>
</DataTemplate>
<DataTemplate x:Key="ComboColumnTemplate">
<ContentControl>
<dxg:GridColumn FieldName="{Binding FieldName}">
<dxg:GridColumn.EditSettings>
<dxe:ComboBoxEditSettings ItemsSource="{Binding Source}"/>
</dxg:GridColumn.EditSettings>
</dxg:GridColumn>
</ContentControl>
</DataTemplate>
<DataTemplate x:Key="ImageColumnTemplate">
<ContentControl>
<dxg:GridColumn FieldName="{Binding FieldName}" Width="100" FixedWidth="True">
<dxg:GridColumn.EditSettings>
<dxe:ImageEditSettings ShowMenu="False"/>
</dxg:GridColumn.EditSettings>
</dxg:GridColumn>
</ContentControl>
</DataTemplate>
<DataTemplate x:Key="SummaryTemplate">
<ContentControl>
<dxg:GridSummaryItem FieldName="{Binding Path=(dxit:DependencyObjectExtensions.DataContext).FieldName, RelativeSource={RelativeSource Self}}"
SummaryType="{Binding Path=(dxit:DependencyObjectExtensions.DataContext).Type, RelativeSource={RelativeSource Self}}"/>
</ContentControl>
</DataTemplate>
</UserControl.Resources>
<Grid>
<dxg:GridControl ItemsSource="{Binding Source}" x:Name="grid"
ColumnsSource="{Binding Columns}"
ColumnGeneratorTemplateSelector="{StaticResource ColumnTemplateSelector}"
ColumnGeneratorStyle="{StaticResource ColumnStyle}"
TotalSummarySource="{Binding TotalSummary}"
TotalSummaryGeneratorTemplate="{StaticResource SummaryTemplate}"
GroupSummarySource="{Binding GroupSummary}"
GroupSummaryGeneratorTemplate="{StaticResource SummaryTemplate}">
<dxg:GridControl.View>
<dxg:TableView x:Name="view" NavigationStyle="Cell" AutoWidth="True"
AllowPerPixelScrolling="True" ShowTotalSummary="True"
IsTotalSummaryMenuEnabled="False"/>
</dxg:GridControl.View>
</dxg:GridControl>
</Grid>
</UserControl>
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reflection;
using System.Xml.Serialization;
using DevExpress.Data;
namespace Model {
public class ViewModel {
public List<string> Cities { get; private set; }
public IList<Employee> Source { get; private set; }
public ObservableCollection<Column> Columns { get; private set; }
public ObservableCollection<Summary> TotalSummary { get; private set; }
public ObservableCollection<Summary> GroupSummary { get; private set; }
public ViewModel() {
Source = EmployeesData.DataSource;
List<string> cities = new List<string>();
foreach(Employee employee in Source) {
if(!cities.Contains(employee.City))
cities.Add(employee.City);
}
Cities = cities;
Columns = new ObservableCollection<Column>() {
new Column() { FieldName="FirstName", Settings = SettingsType.Default },
new Column() { FieldName="LastName", Settings = SettingsType.Default},
new Column() { FieldName="BirthDate", Settings = SettingsType.Default},
new ComboColumn() { FieldName="City", Settings = SettingsType.Combo, Source = Cities },
new Column() { FieldName="ImageData", Settings = SettingsType.Image },
};
TotalSummary = new ObservableCollection<Summary>() {
new Summary() { Type = SummaryItemType.Count, FieldName = "FirstName" },
new Summary() { Type = SummaryItemType.Max, FieldName = "BirthDate" },
};
GroupSummary = new ObservableCollection<Summary>() {
new Summary() { Type = SummaryItemType.Count, FieldName = "FirstName" },
};
}
}
public enum SettingsType { Default, Combo, Image }
public class Summary {
public SummaryItemType Type { get; set; }
public string FieldName { get; set; }
}
public class Column {
public string FieldName { get; set; }
public SettingsType Settings { get; set; }
}
public class ComboColumn : Column {
public IList Source { get; set; }
}
[XmlRoot("Employees")]
public class EmployeesData : List<Employee> {
public static IList<Employee> DataSource {
get {
XmlSerializer s = new XmlSerializer(typeof(EmployeesData));
#if SILVERLIGHT
return (List<Employee>)s.Deserialize(Assembly.GetExecutingAssembly().GetManifestResourceStream("SLGridMVVMBindableClumns.EmployeesWithPhoto.xml"));
#else
return (List<Employee>)s.Deserialize(Assembly.GetExecutingAssembly().GetManifestResourceStream("WPFGridMVVMBindableColumns.EmployeesWithPhoto.xml"));
#endif
}
}
}
public class Employee {
public int Id { get; set; }
public int ParentId { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string JobTitle { get; set; }
public string Phone { get; set; }
public string EmailAddress { get; set; }
public string AddressLine1 { get; set; }
public string City { get; set; }
public string StateProvinceName { get; set; }
public string PostalCode { get; set; }
public string CountryRegionName { get; set; }
public string GroupName { get; set; }
public DateTime BirthDate { get; set; }
public DateTime HireDate { get; set; }
public string Gender { get; set; }
public string MaritalStatus { get; set; }
public string Title { get; set; }
public byte[] ImageData { get; set; }
}
}
using System.Windows.Controls;
using System.Windows;
using Model;
#if SILVERLIGHT
using DevExpress.Xpf.Core.Native;
#endif
namespace View {
public class ColumnTemplateSelector : DataTemplateSelector {
public override DataTemplate SelectTemplate(object item, DependencyObject container) {
Column column = (Column)item;
#if SILVERLIGHT
return (DataTemplate)LayoutHelper.FindParentObject<UserControl>(container).Resources[column.Settings + "ColumnTemplate"];
#else
return (DataTemplate)((Control)container).FindResource(column.Settings + "ColumnTemplate");
#endif
}
}
}