Hello Chris,
I have found a solution, though probably not very elegant.
First I define a new useful class called ObservableDictionary like so (I put it in the utilities folder in my project)
class ObservableDictionary<TKey, TValue> : IDictionary<TKey, TValue>, INotifyCollectionChanged
{
// Implementation
}
This observable dictionary is just like normal dictionary except it implements INotifyCollectionChanged and so is suitable for binding.
Second I store the data in my view-model as a 2 dimension ObservableDictionary like this:
public ObservableDictionary<string, ObservableDictionary<string,double> Data { set; get; }
You access your data like this: Data[rowHeader][columnHeader].
Third I define an extension method in my View source file called GenerateColumns like so:
public static void GenerateColumns(this DataGrid datagrid,
ObservableDictionary<string, ObservableDictionary<string, double> data)
{
datagrid.Columns.Clear();
if (data.Count == 0) return;
datagrid.ItemsSource = data;
foreach (string columnHeader in data.First().Value.Keys)
{
DataGridTextColumn column = new DataGridTextColumn
{
Header = columnHeader,
Binding = new Binding(String.Format("Value[{0}]", columnHeader))
Width = 80
};
datagrid.Columns.Insert(0, column);
}
}
You pass a reference of your data to that method like this:
MyDataGrid.GenerateColumns( ((ViewModelClass)DataContext).Data );
and your columns will be generated and bound to the Data in the view-model.
For this to work, you need to take care of few things:
1 - In your view-model (where Data is) you should handle CollectionChangedEvent by raising onPropertyChanged("Data") in your view-model class.
2 - you should handle PropertyChanged raised earlier in your view by calling
GenerateColumns(((ViewModelClass)DataContext).Data)
3 - Make sure not call these if your View's DataContext == null, you can do this by adding this method to your view class
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (e.Property.Name == "DataContext")
{
((ViewModelClass)DataContext).PropertyChanged += HandlerThatCallsGenerateColumns;
}
}
void HandlerThatCallsGenerateColumns(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Data")
{
MyDataGrid.GenerateColumns(((ViewModelClass)DataContext).Data);
}
}
Tell me how it goes...
Regards,
Ahmad