When engineering a WPF application using the MVVM architectural pattern, you may be required to describe bands in a Model or ViewModel. The GridControl can automatically retrieve settings for bands from a Model or ViewModel.
Assume an Employee view model. It includes the following classes.
- Employee - a data object that contains employee information (e.g., first and last names, job title, etc.).
- ViewModel - the employee view model.
- EmployeeData - a collection of the Employee objects, displayed within grid.
- Column - describes a grid column. This class provides properties that correspond to grid column settings.
- Band - describes a grid band. This class provides the ChildColumns property, which contains the list of child columns for each band.
C# |
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace GridMvvmEnhancements {
public class ViewModel {
public List<Employee> Source { get; private set; }
public ObservableCollection<Band> Bands { get; private set; }
public ViewModel() {
Source = EmployeeData.DataSource;
Bands = new ObservableCollection<Band>() {
new Band() {
Header = "Personal Info",
ChildColumns = new ObservableCollection<Column>() {
new Column() { FieldName = "FirstName" },
new Column() { FieldName = "LastName" },
new Column() { FieldName = "BirthDate" }
}
},
new Band() {
Header = "Location",
ChildColumns = new ObservableCollection<Column>() {
new Column() { FieldName = "City" },
new Column() { FieldName = "Address" }
}
},
new Band() {
Header = "Position",
ChildColumns = new ObservableCollection<Column>() {
new Column() { FieldName = "JobTitle" },
}
}
};
}
}
public class Employee {
public string FirstName { get; set; }
public string LastName { get; set; }
public string City { get; set; }
public string Address { get; set; }
public string JobTitle { get; set; }
public DateTime BirthDate { get; set; }
}
public class EmployeeData : List<Employee> {
public static List<Employee> DataSource {
get {
List<Employee> list = new List<Employee>();
list.Add(new Employee() {
FirstName = "Nathan", LastName = "White", City = "NY", Address = "90 7th Street",
JobTitle = "Sales Manager", BirthDate = new DateTime(1970, 1, 10)
});
list.Add(new Employee() {
FirstName = "Sandra", LastName = "Oldman", City = "LA", Address = "3687 Mohawk Street",
JobTitle = "Marketing Manager", BirthDate = new DateTime(1970, 7, 22)
});
return list;
}
}
}
public class Column {
public string FieldName { get; set; }
}
public class Band {
public string Header { get; set; }
public ObservableCollection<Column> ChildColumns { get; set; }
}
}
|
Note
If the Bands collection might be changed after it has been assigned to the grid control, it should implement INotifyCollectionChanged, so that changes made within a View Model are automatically reflected by the grid.
The GridControl generates bands and their child columns based on band and column templates.
To avoid performance issues when binding to band (and column) properties, use the dxci:DependencyObjectExtensions.DataContext attached property.
To choose the required template based on the band settings, use the template selector.
The code sample below demonstrates how to implement templates for grid bands (see XAML: SingleColumnBandTemplate and MultiColumnBandTemplate) and columns and how to implement the band template selector (the BandTemplateSelector class).
XAML |
<Window x:Class="GridMvvmEnhancements.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
xmlns:dxci="http://schemas.devexpress.com/winfx/2008/xaml/core/internal"
xmlns:local="clr-namespace:GridMvvmEnhancements">
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<Window.Resources>
<local:BandTemplateSelector x:Key="BandTemplateSelector"/>
<DataTemplate x:Key="ColumnTemplate">
<ContentControl>
<dxg:GridColumn FieldName="{Binding Path=(dxci:DependencyObjectExtensions.DataContext).FieldName, RelativeSource={RelativeSource Self}}" />
</ContentControl>
</DataTemplate>
<DataTemplate x:Key="MultiColumnBandTemplate">
<ContentControl>
<dxg:GridControlBand Header="{Binding Path=(dxci:DependencyObjectExtensions.DataContext).Header, RelativeSource={RelativeSource Self}}"
ColumnsSource="{Binding Path=(dxci:DependencyObjectExtensions.DataContext).ChildColumns, RelativeSource={RelativeSource Self} }"
ColumnGeneratorTemplate="{StaticResource ColumnTemplate}">
</dxg:GridControlBand>
</ContentControl>
</DataTemplate>
<DataTemplate x:Key="SingleColumnBandTemplate">
<ContentControl>
<!-- For bands with a single child column. Setting the OverlayHeaderByChildren property to "True" makes a child column to overlay its parent band's header -->
<dxg:GridControlBand Header="{Binding Path=(dxci:DependencyObjectExtensions.DataContext).Header, RelativeSource={RelativeSource Self}}"
ColumnsSource="{Binding Path=(dxci:DependencyObjectExtensions.DataContext).ChildColumns, RelativeSource={RelativeSource Self} }"
ColumnGeneratorTemplate="{StaticResource ColumnTemplate}"
OverlayHeaderByChildren="True" />
</ContentControl>
</DataTemplate>
</Window.Resources>
<Grid>
</Grid>
</Window>
|
C# |
using System.Windows;
using System.Windows.Controls;
namespace GridMvvmEnhancements {
...
public class BandTemplateSelector : DataTemplateSelector {
public override DataTemplate SelectTemplate(object item, DependencyObject container) {
Band band = (Band)item;
if(band.ChildColumns.Count == 1) {
return (DataTemplate)((Control)container).FindResource("SingleColumnBandTemplate");
}
return (DataTemplate)((Control)container).FindResource("MultiColumnBandTemplate");
}
}
}
|
Note
If all grid bands can be described using a single template, you have no need to create a band template selector. Instead, assign this template to the grid's DataControlBase.BandGeneratorTemplate property.
To bind the GridControl to a ViewModel, specify the following properties.
XAML |
<Grid>
<dxg:GridControl Name="grid"
ItemsSource="{Binding Source}"
BandsSource="{Binding Bands}"
BandGeneratorTemplateSelector="{StaticResource BandTemplateSelector}">
<dxg:GridControl.View>
<dxg:TableView AutoWidth="True"/>
</dxg:GridControl.View>
</dxg:GridControl>
</Grid>
|
The image below illustrates the result.
