Reputation: 12131
How would you go about binding a WPF datagrid that needs to display data from many different datasources with varying number of columns with different column headers and types?
What I'm currently doing is creating a custom List<DataGridColumn>()
list of datagrid columns in my ViewModel for each different collection of records to be displayed in this DataGrid.
I Loop over this List to set the DataGrid columns:
foreach (DataGridColumn dgc in dgcSample)
{
dgc.HeaderStyle = hStyle;
dgMyDataGrid.Columns.Add(dgc);
}
Finally, I use the ItemsSource to set the source of items:
dgMyDataGrid.ItemsSource = SomeCollection;
This works but it is not binding and it breaks the MVVM guideline that ViewModel should be agnostic to specific UI elements since it now has to deal with the DataGrid
and host a collection of DataGridColumn
objects...
Any thoughts?
Upvotes: 4
Views: 1013
Reputation: 7433
Have you considered using the datagrid derived class shown in http://www.codeproject.com/KB/grid/MultiColumnSetDataGrid.aspx
This will allow you view to define multiple column sets in your view and switch between them.
Upvotes: 1
Reputation: 19403
IMO the right way of doing this is to encapsulate all the data sources into a single object, that is similar to your custom List<DataGridColumn>()
. Call this MultifunctionalSource
.
This new object will contain a the list of the columns, probably with methods to add new sources and aggregate them. Possibly when adding a new source you could automatically manage the list of columns.
MultifunctionalSource
is responsible for providing a bindable datasource.
The model will provide objects of type MultifunctionalSource
to the View.
Within the view you should have a new control derived from datagrid that will understand how to display objects of type MultifunctionalSource
. This new control will probably be quite simple in the first instance as it can simply setup its columns based on the binding.
MultifunctionalSource
should probably return a list of columns that it thinks are relevant for display. It should also be able to return a complete list of columns to enable the UI to decide which columns are relevant based on other criteria; thus keeping the boundaries.
Upvotes: 1
Reputation: 23871
I think you have to bind your DataGrid
with one datasource, but your task is just creating this datasource.
I'll create a sample for creating a DataSource from different entities using LINQ..
Assuming you have two different entities: Entity1 and Entity2, and each one has common ID:
class Entity1
{
public int ID { get; set; }
public string E1Column { get; set; }
}
class Entity2
{
public int ID { get; set; }
public string E2Column { get; set; }
}
You can create the DataSource using Join in LINQ like the following:
List<Entity1> e1List = new List<Entity1>();
e1List.Add(new Entity1() { ID = 1, E1Column = "E1 a" });
e1List.Add(new Entity1() { ID = 2, E1Column = "E1 b" });
List<Entity2> e2List = new List<Entity2>();
e2List.Add(new Entity2() { ID = 1, E2Column = "E2 a" });
e2List.Add(new Entity2() { ID = 2, E2Column = "E2 b" });
var query = from e1 in e1List
join e2 in e2List on e1.ID equals e2.ID
select new { ID = e1.ID, E1Column = e1.E1Column, E2Column = e2.E2Column };
// Bind the DataGrid
dataGrid1.ItemsSource = query.ToList();
Good luck!
Upvotes: 2