Use dynamic objects to reshape data and display it in a WPF Grid
WPF’s binding syntax offers excellent flexibility when binding to complex data. You can craft intricate binding expressions to display data in the desired form. There are, however, times where binding does not quite cut it. You just have to reshape the data in more fundamental ways.
You can reshape the data with ViewModel specific objects and boiler plate code. But, what fun is there in slogging through all that tedious code? With .NET 4 and dynamic objects, you can avoid all that work and reshape your data with little effort.
Essential Grid offers great support for binding to dynamic data. All you have to do is turn on a single property, IsDynamicItemsSource, and you are on to other tasks.
Consider the sample data below. We have a class named Car. It has 3 simple properties, Model, Manufacturer and price. When displayed, a simple collection of cars will appear as below.
Now, assume that your users require the data to be displayed as below.
· Each car is a column instead of a row.
· The column header is formatted with a combination of properties.
· Price is the only element that appears under each column.
There are many ways to achieve this – depending upon the grid you have chosen. In this case, I am going to use Essential grid. Our grids support for dynamic objects will make the job super-easy.
In our ViewModel we build a collection of dynamic objects as below. The code that reshapes the data is highlighted.
ObservableCollection<Car> list = new ObservableCollection<Car>();
ObservableCollection<dynamic> dynamicList = new ObservableCollection<dynamic>();
public ViewModel()
{
list.Add(new Car(“Corolla”, “Toyota”, 10001));
list.Add(new Car(“Accord”, “Honda”, 10002));
list.Add(new Car(“MDX”, “Acura”, 10007));
list.Add(new Car(“ES 300”, “Lexus”, 10005));
list.Add(new Car(“LX 470”, “Lexus”, 10008));
list.Add(new Car(“Taurus”, “Ford”, 10001));
list.Add(new Car(“Volt”, “Chevy”, 10003));
list.Add(new Car(“S60”, “Volvo”, 10004));
ExpandoObject o = new ExpandoObject();
foreach (var mc in list)
{
IDictionary<String, object> od = (IDictionary<String, object>)o;
string displayName = string.Format(“{0}-{1}”, mc.Manufacturer, mc.Model);
od[displayName + “-price”] = mc.Price;
}
dynamicList.Add(o);
}
//return the dynamic data
public IListDynamicData { get { return dynamicList; } }
I am simply creating ExpandoObjects and assigning values to the dynamic members. This new list can then be directly bound to the grid (works in XAML also).
public MainWindow() { InitializeComponent(); ViewModel vm = new ViewModel(); dataGrid.IsDynamicItemsSource = true; dataGrid.ItemsSource = vm.DynamicData; }
That’s all there is to it. Point WPF DataGrid to a dynamic object list, set a single property, and you are done.
A complete code sample is available for download here.