XAML DataGrid Binding Data Columns or Rows dynamically using MVVM design Pattern

The C# and XAML code sample below describes about how to bind data (columns and rows) to DataGrid dynamically in Silverlight and WPF using MVVM design pattern.

Create a New Silverlight or WPF project and create the MVVM Folder structure as View, ViewModel and Model
a) Add new XAML user control View.XAML to View folder and add the “DataGrid” Control to created XAML file as below.

<sdk:DataGrid Margin="5" AutoGenerateColumns="False" > </sdk:DataGrid>

b) Add new Class file ViewModel.cs to ViewModelFolder and add Constructor to .cs file as below

public DataGrid_Dynamic_DataViewModel()
{
}

c) In most of the cases, DataGrid Column Header would be different from the table column in DB. So, create a Class “DataGridColumns.cs” with Properties “DisplayColumnName”, used to bind as DataGridColun Header and “BindingProperty”, used as Binding for DataGridColumn.

public class DataGridColumns
{
public string DisplayColumnName { get; set; }

public string BindingPropertyName { get; set; }
}

d) For bindings, Use C# 4.0 dynamics feature “ExpandoObject” which represents an object whose members can be dynamically added or removed. In this case, columns required to bind DataGrid will be dynamically added with their values.
If you are using lower versions of .Net Framework, use IDictionary in place of “ExpandoObject”

e) In ViewModel, add two Binding Properties, one is for list of columns and another one is for data as below.

public ObservableCollection<DataGridColumns> GridViewColumns { get; set; }
public ObservableCollection<ExpandoObject> GridViewRowCollection { get; set; }

public ObservableCollection<ExpandoObject> DataCollection
{
get
{
return this.GridViewRowCollection;
}
}

f) Now Prepare the Columns Collection and Data Collection as below. In your case, if required use DB call to fetch this required data and then prepare both the collections.

           this.GridViewColumns = new ObservableCollection<DataGridColumns>();
this.GridViewColumns.Add(new DataGridColumns { DisplayColumnName = "Employee Id", BindingPropertyName = "ID" });
this.GridViewColumns.Add(new DataGridColumns { DisplayColumnName = "Employee Name", BindingPropertyName = "Name" });
this.GridViewColumns.Add(new DataGridColumns { DisplayColumnName = "Employee Designation", BindingPropertyName = "Designation" });
this.GridViewColumns.Add(new DataGridColumns { DisplayColumnName = "Department", BindingPropertyName = "Category" });

this.GridViewRowCollection = new ObservableCollection<ExpandoObject>();
var item =new ExpandoObject() as IDictionary<string, object>;

//Add key as Binding Property and value as Row Value to be displayed
item.Add("ID", "0001");
item.Add("Name", "Test Emloyee1");
item.Add("Designation", "Consultant");
item.Add("Category", "Finance");

this.GridViewRowCollection.Add((ExpandoObject)item);

item =new ExpandoObject() as IDictionary<string, object>;
item.Add("ID", "0002");
item.Add("Name", "Test Emloyee2");
item.Add("Designation", "SE");
item.Add("Category", "Banking");

this.GridViewRowCollection.Add((ExpandoObject)item);

g) Open the XAML file and add this ViewModel.cs file as DataContext and then bind the property “DataCollection” as ItemSource to DataGrid.

<UserControl.DataContext>
<viewModel:DataGrid_Dynamic_DataViewModel></viewModel:DataGrid_Dynamic_DataViewModel>
</UserControl.DataContext>
    <sdk:DataGrid Margin="5 AutoGenerateColumns="False" ItemsSource="{Binding DataCollection}"></sdk:DataGrid>

h) Create attached Dependency property “ColumnsCollection” by creating new class file as below.

     public class GridViewBindingBehavior
{
       public static readonly DependencyProperty ColumnsCollectionProperty = DependencyProperty.RegisterAttached("ColumnsCollection", typeof(ObservableCollection<DataGridColumns>), typeof(GridViewBindingBehavior), new PropertyMetadata(OnColumnsCollectionChanged));

       public static void SetColumnsCollection(DependencyObject o, ObservableCollection<ColumnDefinition> value)
{
o.SetValue(ColumnsCollectionProperty, value);
}

        public static ObservableCollection<ColumnDefinition> GetColumnsCollection(DependencyObject o)
{
return o.GetValue(ColumnsCollectionProperty) as ObservableCollection<ColumnDefinition>;
}

private static void OnColumnsCollectionChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
DataGrid gridView = o as DataGrid;

if (gridView == null)
{
return;
}

gridView.Columns.Clear();

if (gridView.ItemsSource == null)
{
return;
}

ObservableCollection<ExpandoObject> objExpando = (ObservableCollection<ExpandoObject>)gridView.ItemsSource;

if (e.NewValue == null)
{
return;
}

var collection = e.NewValue as ObservableCollection<DataGridColumns>;

if (collection == null)
{
return;
}
foreach (var column in collection)
{
var gridViewColumn = GetDataColumn(column);
gridView.Columns.Add(gridViewColumn);
}
}
private static DataGridTextColumn GetDataColumn(DataGridColumns columnName)
{
var column = new DataGridTextColumn();
column.IsReadOnly = true;
column.Header = columnName.DisplayColumnName;
column.Binding = new Binding();

column.Binding.Converter = new ColumnValueConverter();
column.Binding.ConverterParameter = columnName.BindingPropertyName;

return column;
}
}

J) Create a Converter which is used to convert the ExpandoObject to the required Binding property as highlighted above.

    public class ColumnValueConverter : IValueConverter
{

object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var row = value as IDictionary<string, object>;
string columnName = (string)parameter;
return (row[columnName]);
}


object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

k) Again, open the XAML file and add this attached property with the Columns Collection as below.

<sdk:DataGrid Margin="5" AutoGenerateColumns="False" ItemsSource="{Binding DataCollection}" viewModel:GridViewBindingBehavior.ColumnsCollection="{Binding GridViewColumns}" >
</sdk:DataGrid>

Download the attached sample for your reference from
Download Code Sample .

By Siva Jagan Dhulipalla   Popularity  (7146 Views)