I need to bind WPF DataGrid to an observable list of objects and I need public properties of the objects to determine the columns of the grid. the grid needs to update every time property is changed. I need to generate this grid automatically and dynamically depending on the class in the observable collection, as I do not know what properties the object will have (e.g. inherited classes may add new properties).
I have managed to make such grid: columns are added automatically, new items added to the collection are instantly visible in the grid. however, I do not know how to inform the grid of the change in the properties. I have seen many answers to SIMILAR problems like:
How do I bind a WPF DataGrid to a variable number of columns?
or
How do I dynamically generate columns in a WPF DataGrid?
but none of them was addressing exactly the problem I have.
ok, my code. my grid with item source binding:
<DataGrid Name="connectedClientGrid" CanUserAddRows="False" AutoGenerateColumns="true" CanUserSortColumns="False" ItemsSource="{Binding}" HorizontalAlignment="Left" Margin="10,77,0,0" VerticalAlignment="Top" Height="188" Width="550"/>
in window code it is linked to a observable collection:
public ObservableCollection<ClientController> clientControllers = new ObservableCollection<ClientController>();
connectedClientGrid.AutoGeneratingColumn += ColumnNameAttribute.dgPrimaryGrid_AutoGeneratingColumn;
connectedClientGrid.ItemsSource = clientControllers;`
ColumnNameAttribute allows to create columns out of object properties:
public class ColumnNameAttribute : System.Attribute
{
public ColumnNameAttribute(string Name) { this.Name = Name; }
public string Name { get; set; }
static public void dgPrimaryGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
var desc = e.PropertyDescriptor as PropertyDescriptor;
var att = desc.Attributes[typeof(ColumnNameAttribute)] as ColumnNameAttribute;
if (att != null)
{
e.Column.Header = att.Name;
}
}
}
it is used in the observed class like this:
public partial class ClientController
{
//properties observed by the interface as grid columns. Inheriting classes may add more properties that will be monitored automatically
[ColumnName("ID")] public virtual string id {get; set;}
[ColumnName("Status")] public string status { get; set; }
[ColumnName("Last message to client")] public string lastSentMessage { get; set; }
}
this works very well. the only problem is I do not know how to use sth like INotifyPropertyChanged and PropertyChangedEventHandler IN THIS SPECIFIC CASE to notify the grid that property has been changed. at the moment I do
var tmp = connectedClientGrid.ItemsSource;
connectedClientGrid.ItemsSource = null;
connectedClientGrid.ItemsSource = tmp;
every second to make sure grid is refreshed. this works, but it is ugly and I want to find an elegant solution based on binding. thanks for any help.