tags:

views:

145

answers:

2

major edit of a tumbleweed, may remain a tumbleweed...

If I have a list of Customers and the data for each Customer is contained in a Dictionary how can I bind the list to the DataGrid so that each string key is a column?

Edit: N.B. I know it's not a nice way to design a Customer class.

e.g.

public class Customer{

    public int Id{get;set;}

    private Dictionary<string,string> values;

    public Dictionary<string,string> Values{get {return values;}}

    public Customer(int id){
         this.Id = id;
         values["Name"] = "Peter";
         values["Age"] = 129.ToString();
         values["HairColour"] = "See through!";
    }
}

... later that day...

var Customers = new List<Customer>(){
    new Customer(1),
    new Customer(2), 
    new Customer(3)
};

... and then...

<DataGrid ItemsSource={Binding Path=Customers}/>

... desired result.

Id | Name | Age |  HairColour
________________________
1  | Peter| 129 | See through!
________________________

2  | Peter| 129 | See through!
________________________

3  | Peter| 129 | See through!
________________________
A: 

I don't get the design of your Customer class. Much safer would be a customer class as follows. That would also make binding much easier.

public class Customer
{
    public int Id { get; set; }

    public string Name { get; set; }

    public int Age { get; set; }

    public HairColor HairColor { get; set; }
}

public enum HairColor
{
    SeeThrough,
    Black,
    Brown,
    Blond
}

If the reason is that this is because that is how you get it from a database, then consider your class as Model and my class as ViewModel, with appropriate transformation done in the ViewModel class.

Daniel Rose
I'd much rather use a safely typed approach, unfortunately with what i'm working on I have to consider displaying fields from a data source (an excel spread sheet) where I can't predict exactly how many fields are contained in a customer. My client wants it to be flexible.
panamack
A: 

In the absence of other suggestions this article is the best answer I can come up with. In his article Miron is working with XML data from a web service and converts it into a Reflection generated type for databinding.

I can follow his approach and create a type that uses my Dictionary keys rather than xml nodes as the source for the properties of the generated type. For the otherwise simple application I'm building it seems rather hefty but at least I get to learn about the Reflection API.

If anyone cares to comment or can still provide me with a better solution I'd appreciate it.


Or, the easy road...

public partial class Window2 : Window
{
    public Window2()
    {
        InitializeComponent();

        var a1 = new A();
        a1["Name"] = "Jack";
        a1["Age"] = "9";

        var a2 = new A();
        a2["Name"] = "Jill";
        a2["Age"] = "7";

        List<A> items = new List<A>() { a1, a2 };

        this.DataBoundItems = items;

        dg.DataContext = this;
    }

    public List<A> DataBoundItems { get; set; }

    private void dg_DataContextChanged(
        object sender, 
        DependencyPropertyChangedEventArgs e)
    {
        foreach (string key in DataBoundItems[0].Values.Keys)
        {
            var col = new DataGridTextColumn();
            col.Header = key;
            //  bind to the indexer on the class
            col.Binding = new Binding("[" + key + "]");
            dg.Columns.Add(col);
        }
    }
}

public class A
{
    private Dictionary<string, string> values = new Dictionary<string, string>();

    public string this[string index]
    {
        get
        {
            return values[index];
        }
        set
        {
            values[index] = value;
        }
    }

    public Dictionary<string, string> Values { get { return aValues; } }
}
panamack