Reputation: 3
I have a double list I need to have shown sort of in a spreadsheet-like way, and I'm not sure what would be the best approach.
C#:
public class ViewModelClass
{
public List<ClassA> Data {get;set;}
//more code
}
public class ClassA
{
public string ColumnName {get;set;}
public List<ClassB> Values {get;set;}
//more code
}
public class ClassB
{
public string DisplayValue {get;set;}
//more code
}
It should be shown as
Row | Item1 | Item2 | Item3 |
---|---|---|---|
1 | Value1.1 | Value2.1 | Value3.1 |
2 | Value2.2 | Value3.1 | |
3 | Value 2.3 |
from a dataset of
ViewModelClass vm;
...
vm.Data.Add(new ClassA { ColumnName="Item1", Values=new List<ClassB>() { new ClassB { DisplayValue="Item1.1" }}};
vm.Data.Add(new ClassA { ColumnName="Item2", Values=new List<ClassB>() { new ClassB { DisplayValue="Item2.1" },
new ClassB { DisplayValue="Item2.2" },new ClassB { DisplayValue="Item2.3" }}};
vm.Data.Add(new ClassA { ColumnName="Item3", Values=new List<ClassB>() { new ClassB { DisplayValue="Item3.1" },
new ClassB { DisplayValue="Item3.2" }}};
I found this thread, though it wasn't quite what I wanted: https://social.msdn.microsoft.com/Forums/vstudio/en-US/da5f36df-91e1-4a1a-9265-25c9a2b56414/binding-list-of-lists-to-datagrid?forum=wpf
My current code is
var vm = DataContext as ViewModelClass;
MyDataGrid.Columns.Clear();
MyDataGrid.Columns.Add(new DataGridTextColumn { Header = "Row" });
int count = vm.Data.Count;
for (int i = 0; i < count; i++)
{
var col = new DataGridTextColumn { Header = vm.Data[i].ColumnName, Binding = new Binding($"Values") };
MyDataGrid.Columns.Add(col);
}
Which gives me the right headers, but the rows are all "(Collection)"
Upvotes: 0
Views: 82
Reputation: 28988
To create a table like the one in your image you must redesign your class to represent a row based data structure.
If you don't want to use DataTable
as data source for the DataGrid
, then your class must be designed that it contains properties that each map to a column. The property's name is the column name by default. The class itself their represents a row.
The following example creates a type that has three columns named Item1...Item3:
class MyRowData : INotifyPropertyChanged
{
// TODO:: Let all property setters raise the PropertyChanged event
public string Item1 { get; set; }
public string Item2 { get; set; }
public string Item3 { get; set; }
}
This is your basic data structure.
To create the rows, you create the instances of MyRowData
and add them to a collection that binds to the DataGrid.ItemsSource
property:
// ItemsSource for the DataGrid
public ObservableCollection<MyRowData> TableData { get; }
for (int i = 1; i < 4; i++)
{
var newRow = new MyRowData
{
Item1 = $"Value1.{i}",
Item2 = $"Value2.{i}",
Item3 = $"Value3.{i}"
};
this.TableData.Add(newRow);
}
To enable the DataGrid
to update itself with modified data, your data model (in this case MyRowData
) must implement INotifyPropertyChanged
.
Upvotes: 2