Joshua
Joshua

Reputation: 1584

In C#, How to bind a Dictionary to a DataGridView?

I have a DataGridView (dgv_Orders) and a Dictionary(orders<uint, Order>). Class Order has the following members: uint order_id, uint volume, double price I would like to be able to have dgv_orders display all of the values contained in the dictionary, row by row, listing out all of their properties. I need the Dictionary structure, so that I can edit the values in O(1) time.

I have gotten this to work with a BindingList & I have also looked at the following solution..

https://stackoverflow.com/a/854969/1143465

and gotten it to almost work, except that the DataGridView just has the columns, Key & Value, whereas I would like it to show order_id, volume, & price. Are there any ways to do so?

Thanks in advance!

class Order : INotifyPropertyChanged
{
    private uint order_id;
    private double price;
    private uint volume;

    public event PropertyChangedEventHandler PropertyChanged;

    public Order(uint order_id)
    {
        this.order_id = order_id;
        price = 10.0;
        volume = 1;
    }

    public uint Order_ID
    {
        get { return order_id; }
        set { order_id = value; NotifyPropertyChanged("Order_ID"); }
    }

    public uint Price
    {
        get { return price; }
        set { price = value; NotifyPropertyChanged("Price"); }
    }

    public uint Volume
    {
        get { return volume; }
        set { volume = value; NotifyPropertyChanged("Volume"); }
    }

    private void NotifyPropertyChanged(string name)
    {
         if(PropertyChanged != null)
             PropertyChanged(this, new PropertyChangedEventArgs(name));
    }
}

Upvotes: 0

Views: 6761

Answers (3)

competent_tech
competent_tech

Reputation: 44971

I think your only option is to bind to the Values property of the dictionary.

Well, actually, that's not entirely true. You could create a new class that inherits from dictionary and then implement the IBindingList or IObservableCollection interfaces.

All of our core collection class inherit from System.Collections.ObjectModel.KeyedCollection which has similar performance characteristics as dictionary (provides both O(1) indexed retrieval and keyed retrieval that approaches O(1)), but is also more easily serialized over WCF and Web Services than dictionaries.

Update

Here is an example of a collection for your order class:

public class OrderCollection : System.Collections.ObjectModel.KeyedCollection<uint, Order>
{
    protected override uint GetKeyForItem(Order item)
    {
        return item.Order_ID;
    }
}

I was able to successfully test this with the following code and a new, default datagridview:

        var cOrders = new OrderCollection();

        cOrders.Add(new Order(1));
        cOrders.Add(new Order(2));
        cOrders.Add(new Order(3));

        dataGridView1.DataSource = cOrders;

Upvotes: 1

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112762

As others have pointed out, it is possible to bind to a Dictionary<T>, but is it reasonable? The purpose of a dictionary is to lookup values form a given key, what the DataGridView will not do. A List<T> that allows access to individual items through an index seems more appropriate. A List<T> can also be sorted in a meaningful way, where as the dictionary will yield a completely 'wild' order based on hash values.

Upvotes: 0

MethodMan
MethodMan

Reputation: 18863

Use this as a starting example and change the variables to match your usecase.

Dictionary<string, double> someDictionary = new Dictionary<string, double>();
BindingSource _bindingSource = new BindingSource();
dataGridView1.DataSource = _bindingSource;
_bindingSource.DataSource = someDictionary;

Upvotes: 1

Related Questions