WPF: Best way to create bindings to unknown types in MVVM

A DataGrid seems inappropriate in this case. If your list was bound to two separate entities, it would break badly.

A better option would potentially be to use some other ItemsControl and set up a DataTemplate for each type of Entity. This would allow you to build custom editors per entity, and have a "list" of them to edit.

If you know the entities will always be of a single type, I'd instead build the collection of that specific type, and bind to it.


Since you don't know the property names of the Entities beforehand, I think your best option is to keep your DataGrid in Xaml but move the defintion and the Bindings of its DataGridColumns to the code behind.

AddColumnsForProperty(PropertyInfo property, string parentPath = "")
{
     var title = property.Name;
     var path = parentPath + (parentPath=="" ? "" : ".") + property.Name;

     if(property.PropertyType == typeof(string))
     {
        var column = new DataGridTextColumn();
        column.Header = title;
        column.Binding = new Binding(path);
        dataGrid.Columns.Add(column);
     }
     else if(property.PropertyType == typeof(bool))
     {
        //use DataGridCheckBoxColumn and so on
     }
     else
     {
          //...
     }

     var properties = property.GetProperties();
     foreach(var item in properties)
     {
          AddColumnsForProperty(item, path);
     }
}

Now if you execute these you'll have your dataGrid columns filled. and by adding all instances of the desired type in an observable collection and bind it to ItemsSource of the DataGrid it should work. selectedItem should be an instance of one the classes derived from Entity. The listbox contains new A() and new B() (or any existing instances of A and B) so selectedItem can be used in the following statement.

var propertyList = selectedItem.GetType().GetProperties();
foreach (var property in propertyList) 
    AddColumnsForProperty(PropertyInfo property);

how to write DataGridColumnTemplate in code


Edit:

Member can't be used in this scenario because INotifyPropertyChanged should get involved, so I replaced members with properties.