tags:

views:

65

answers:

2

Hi!

I want to display and edit some objects in a WPF data grid and I'm looking for a good way to do so. All objects I want to display have the same fields, but every execution the fields of my objects can differ. Here is a piece of the interface to illustrate what I mean:

public interface IMyObject
{
    IEnumerable<string> GetFieldNames();
    IEnumerable<Type> GetFieldTypes();

    object GetField(string name);
    void SetField(string name, object value);
}

How can I generate a data grid which displays this kind of objects? I thought of XAML generation to define the columns, but I'm still facing the problem of accessing the fields. I think I could realize this with value converters, another option would be to dynamically create a type which exposes the dynamic fields with properties.

Are there any other ways and which should I favor? I'm keen on hearing your opinions.

Best Regards,
Oliver Hanappi

+1  A: 

I would do this to my interface

public interface IMyObject
{
    IEnumerable<string> GetFieldNames();
    IEnumerable<Type> GetFieldTypes();

    //i would add this property, then you can bind directly to it.
    //basically it is a collection indexer, indexed by string
    object this[String name] { get; set; }

    object GetField(string name);
    void SetField(string name, object value);
}

I would build the columns in code like so, (where stringKeyCollection is a collection of strings returned from GetFieldNames() - although personally i would keep this information separate from my object - like a master definition)

foreach(String item in stringKeyCollection){
   //create the base column (use whatever column type you want
   DataGridBoundColumn column = new DataGridBoundColumn();
   //create the binding for the column
   column.Binding = new Binding("[" + item + "]");
   //set the header
   column.Header = item;
}

then you have objects in each cell of the grid and you can define templates however you wish.

Aran Mulholland
I was not aware of the possibility to bind to the indexer of an object. I think this solution suits best my needs.
Oliver Hanappi
A: 

The fact that the type of your bound objects changes each time is not hugely important, if your grid is set to AutoGenerate columns then it will create the columns for you. However this could lead to some rather un-pretty results.

What i would suggest is this:

  • with your data objects, annotate each displayable property with a custom attribute, this is simply to mark it for later inspection
  • once you have obtained your collection of items, take the first item in the list and pass it to a factory function that returns grid columns
  • the grid column factory function can inspect the data object using reflection looking for properties with the special attribute you used earlier, and create the appropriate grid column with the appropriate binding and value converter
  • add the collection of grid columns to the grid, and bind the data

this approach depends upon all the items in the collection being of the same type, but should be reasonably snappy. If you have different items in the collection and they have little or no commonality then you could look to the method where you query each item for it's bindable properties and then mash the whole lot together.

slugster