I have a list of object, each object contains user defined attributes. The keys and values for these attributes are free string, so they are not necessarily consistent between objects. Regardless, I would like to display all my objects in a table.
One object per row, one attribute key per column, one attribute value per cell like so :
name | age | favourite fruit | favourite color | city |
---|---|---|---|---|
john | 21 | blue | london | |
jane | ananas | red | paris | |
paul | 22 | banana | green | |
patricia | 23 | ananas | istanbul |
I have a custom objects responsible for reading the attribute and storing them in a Dictionary<string, string>
and my model view stores a list of such dictionaries. I would like to link this list of dictionary to my WPF control.
Later, column would need to be sortable and groupable by attribute value (like excel subtotals)
I don't even know where to start ? Custom dataGridView ? Custom ListView?
A DataTable
object is the way to go for dynamic data. You will have to convert it by doing something similar to what is below, but instead iterating through your objects.
public partial class DataGridFromDictionary : Window
{
public DataTable Table { get; set; }
public DataGridFromDictionary()
{
var attributeDictionaries = new List<Dictionary<string, string>>()
{
new Dictionary<string, string>()
{
{"name", "john" },
{"age", "21" },
{"favourite color", "blue" },
{"city", "london" },
},
new Dictionary<string, string>()
{
{"name", "jane" },
{"favourite fruit", "ananas" },
{"favourite color", "red" },
{"city", "paris" },
},
};
Table = CovertToDataTable(attributeDictionaries);
InitializeComponent();
DataContext = this;
}
}
Dictionary
to DataTable
converterThis will allow you to convert your data into something that the DataGrid
can consume.
public DataTable CovertToDataTable(List<Dictionary<string, string>> dynamicObjects)
{
DataTable table = new DataTable();
foreach(var attributeDictionary in dynamicObjects)
{
// add any missing columns
foreach (var attribute in attributeDictionary.Keys)
{
if (!table.Columns.Contains(attribute))
{
table.Columns.Add(attribute);
}
}
// create the new row
var dr = table.NewRow();
foreach (var attribute in attributeDictionary)
{
dr[attribute.Key] = attribute.Value;
}
table.Rows.Add(dr);
}
return table;
}
<Grid>
<DataGrid ItemsSource="{Binding Table}" />
</Grid>