How to: Bind the Grid to Bands Specified in ViewModel

  • 7 minutes to read

This topic describes how to define bands in a View Model and display them in the GridControl.

View Example: How to Bind the GridControl to a Collection of Bands Specified in a ViewModel

Assign ViewModel Bands to the GridControl

The following example demonstrates how to display employee information from the data model in the GridControl.

DevExpress WPF | Grid Control - MVVM Bands Default

  1. Create classes that describe a grid band and its child column:

    public class Band : BindableBase {
        public Band(string header, ObservableCollection<Column> childcolumns) {
            Header = header;
            ChildColumns = childcolumns;
        }
        public string Header { get; }
        public ObservableCollection<Column> ChildColumns { get; }
    }
    
    public class Column : BindableBase {
        public Column(string fieldname) {
            FieldName = fieldname;
        }
        public string FieldName { get; }
    }
    
  2. Specify a collection of bands in the ViewModel:

    public class ViewModel : ViewModelBase {
        public ViewModel() {
            // ...
            Bands = new ObservableCollection<Band>() {
                new Band(
                    "Personal Info",
                    new ObservableCollection<Column>() {
                        new Column(nameof(Employee.FirstName)),
                        new Column(nameof(Employee.LastName)),
                        new Column(nameof(Employee.BirthDate))
                    }
                ),
                new Band(
                    "Location",
                    new ObservableCollection<Column>() {
                        new Column(nameof(Employee.Country)),
                        new Column(nameof(Employee.City))
                    }
                )
            };
        }
        // ...
        public ObservableCollection<Band> Bands { get; }
    }
    

    If you want the GridControl to reflect changes made in the Bands collection, this collection should implement the INotifyCollectionChanged interface.

  3. Add the column and band templates to your project. The GridControl generates bands and their child columns based on these templates.

    Use the DependencyObjectExtensions.DataContext attached property when you bind the GridControl to band and column properties. This attached property synchronizes data updates of bound properties to enhance grid performance:

    <Window.Resources>
        <DataTemplate x:Key="ColumnTemplate">
            <dxg:GridColumn FieldName="{Binding Path=(dxci:DependencyObjectExtensions.DataContext).FieldName, RelativeSource={RelativeSource Self}}" />
        </DataTemplate>
        <DataTemplate x:Key="MultiColumnBandTemplate">
            <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}" />
        </DataTemplate>
    </Window.Resources>
    
  4. Assign the band collection to the DataControlBase.BandsSource property. Set the DataControlBase.BandGeneratorTemplate property to a template that generates bands:

    <dxg:GridControl ...
                     BandsSource="{Binding Bands}" 
                     BandGeneratorTemplate="{StaticResource MultiColumnBandTemplate}" />
    

Add a Single Column Band

Follow the steps below to add a band template. In this example, the SingleColumnBandTemplate adds a band with only one child column. This column’s header overlays the parent band’s header:

DevExpress WPF | Grid Control - MVVM Bands Multiple Templates

  1. Add a band with a single child column to the Bands collection:

    public class ViewModel : ViewModelBase {
        public ViewModel() {
            // ...
            Bands = new ObservableCollection<Band>() {
                new Band(
                    // ...
                ),
                new Band(
                    // ...
                ),
                new Band(
                    "Position",
                    new ObservableCollection<Column>() {
                        new Column(nameof(Employee.JobTitle))
                    }
                )
            };
        }
        // ...
        public ObservableCollection<Band> Bands { get; }
    }
    
  2. Create a template that generates bands for individual columns. Set the BandBase.OverlayHeaderByChildren property to true to display the child column’s header over the band’s header:

    <Window.Resources>
        <DataTemplate x:Key="SingleColumnBandTemplate">
            <dxg:GridControlBand ColumnsSource="{Binding Path=(dxci:DependencyObjectExtensions.DataContext).ChildColumns, RelativeSource={RelativeSource Self}}" 
                                 ColumnGeneratorTemplate="{StaticResource ColumnTemplate}" 
                                 OverlayHeaderByChildren="True" />
        </DataTemplate>
    </Window.Resources>
    

Add a Template Selector to Choose among Multiple Templates

Your application now contains the MultiColumnBandTemplate and SingleColumnBandTemplate. To choose a template based on the band type, create a template selector and assign it to the DataControlBase.BandGeneratorTemplateSelector property:

public class BandTemplateSelector : DataTemplateSelector {

    public DataTemplate SingleColumnBandTemplate { get; set; }
    public DataTemplate MultiColumnBandTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container) {
        Band band = item as Band;
        if(band == null) return null;
        if(band.Header == "Position") {
            return SingleColumnBandTemplate;
        }
        return MultiColumnBandTemplate;
    }
}
<Window.Resources>
    <!-- ... -->
    <local:BandTemplateSelector x:Key="BandTemplateSelector" 
                                MultiColumnBandTemplate="{StaticResource MultiColumnBandTemplate}" 
                                SingleColumnBandTemplate="{StaticResource SingleColumnBandTemplate}"/>
</Window.Resources>
<dxg:GridControl ...
                 BandsSource="{Binding Bands}" 
                 BandGeneratorTemplateSelector="{StaticResource BandTemplateSelector}"/>

Add a Multilevel Band Structure

If you want to display child bands in the GridControl, follow the steps below:

DevExpress WPF | Grid Control - MVVM Child Bands

  1. Add a property that returns a collection of child bands to the Band class:

    public class Band : BindableBase {
        public Band(string header, ObservableCollection<Column> childcolumns, ObservableCollection<Band> childbands) {
            Header = header;
            ChildColumns = childcolumns;
            ChildBands = childbands;
        }
        public string Header { get; }
        public ObservableCollection<Column> ChildColumns { get; }
        public ObservableCollection<Band> ChildBands { get; }
    }
    
  2. Specify the Bands collection:

    public class ViewModel : ViewModelBase {
        public ViewModel() {
            // ...
            Bands = new ObservableCollection<Band>() {
                new Band(
                    "Personal Info",
                    new ObservableCollection<Column>(),
                    new ObservableCollection<Band>() {
                        new Band (
                            "Name",
                            new ObservableCollection<Column>() {
                                new Column(nameof(Employee.FirstName)),
                                new Column(nameof(Employee.LastName))
                            },
                            new ObservableCollection<Band>()
                        ),
                        new Band (
                            "Birthday",
                            new ObservableCollection<Column>() {
                                new Column(nameof(Employee.BirthDate))
                            },
                            new ObservableCollection<Band>()
                        )
                    }
                ),
                new Band(
                    "Location",
                    new ObservableCollection<Column>() {
                        new Column(nameof(Employee.Country)),
                        new Column(nameof(Employee.City))
                    },
                    new ObservableCollection<Band>()
                ),
                new Band(
                    "Position",
                    new ObservableCollection<Column>() {
                        new Column(nameof(Employee.JobTitle))
                    },
                    new ObservableCollection<Band>()
                )
            };
        }
        // ...
        public ObservableCollection<Band> Bands { get; }
    }
    
  3. Create a template that generates child bands:

    <Window.Resources>
        <DataTemplate x:Key="ChildBandTemplate">
            <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}"/>
        </DataTemplate>
    </Window.Resources>
    
  4. Modify the MultiColumnBandTemplate. Specify the BandBase.BandsSource property and assign the child band template to the BandBase.BandGeneratorTemplate property:

    <Window.Resources>
        <DataTemplate x:Key="MultiColumnBandTemplate">
            <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}"
                                 BandsSource="{Binding Path=(dxci:DependencyObjectExtensions.DataContext).ChildBands, RelativeSource={RelativeSource Self}}"
                                 BandGeneratorTemplate="{StaticResource ChildBandTemplate}"/>
        </DataTemplate>
    </Window.Resources>
    
See Also