Datagridview Bound to a Dictionary

DataGridView bound to a Dictionary

There are a couple of issues with Dictionary; the first is (as you've found) it doesn't implement the necessary IList/IListSource. The second is that there is no guaranteed order to the items (and indeed, no indexer), making random access by index (rather than by key) impossible.

However... it is probably doable with some some smoke and mirrors; something like below:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;

static class Program
{
[STAThread]
static void Main()
{
Dictionary<string, decimal> prices =
new Dictionary<string, decimal>();
prices.Add("foo", 123.45M);
prices.Add("bar", 678.90M);

Application.EnableVisualStyles();
Form form = new Form();
DataGridView dgv = new DataGridView();
dgv.Dock = DockStyle.Fill;
form.Controls.Add(dgv);
var bl = prices.ToBindingList();
dgv.DataSource = bl;
Button btn = new Button();
btn.Dock = DockStyle.Bottom;
btn.Click += delegate
{
prices.Add(new Random().Next().ToString(), 0.1M);
bl.Reset();
};
form.Controls.Add(btn);
Application.Run(form);
}

public static DictionaryBindingList<TKey, TValue>
ToBindingList<TKey, TValue>(this IDictionary<TKey, TValue> data)
{
return new DictionaryBindingList<TKey, TValue>(data);
}
public sealed class Pair<TKey, TValue>
{
private readonly TKey key;
private readonly IDictionary<TKey, TValue> data;
public Pair(TKey key, IDictionary<TKey, TValue> data)
{
this.key = key;
this.data = data;
}
public TKey Key { get { return key; } }
public TValue Value
{
get
{
TValue value;
data.TryGetValue(key, out value);
return value;
}
set { data[key] = value; }
}
}
public class DictionaryBindingList<TKey, TValue>
: BindingList<Pair<TKey, TValue>>
{
private readonly IDictionary<TKey, TValue> data;
public DictionaryBindingList(IDictionary<TKey, TValue> data)
{
this.data = data;
Reset();
}
public void Reset()
{
bool oldRaise = RaiseListChangedEvents;
RaiseListChangedEvents = false;
try
{
Clear();
foreach (TKey key in data.Keys)
{
Add(new Pair<TKey, TValue>(key, data));
}
}
finally
{
RaiseListChangedEvents = oldRaise;
ResetBindings();
}
}

}
}

Note that the use of a custom extension method is entirely optional, and can be removed in C# 2.0, etc. by just using new DictionaryBindingList<string,decimal>(prices) instead.

How to bind a Dictionary to DataSource of DataGridView

Check out the docs for the DataSource property. It only handles specific types (IList, IListSource etc.). So you cannot bind it to an IDictionary. So, this will work:

List<KeyValuePair<string, string>> d = new List<KeyValuePair<string, string>>();
d.Add(new KeyValuePair<string, string>("1", "2323"));
d.Add(new KeyValuePair<string, string>("2", "1112323"));

DataGridView v = new DataGridView();
v.DataSource = d;

Datagridview bound to Dictionary in vb.net

The conversion should be:

Dim _priceDataArray =
From row In _priceDataNew
Select New With {
Key .Item = row.Key,
Key .Price = row.Value
}

Binding a Dictionary to the DataGridView in C#?

I know this is a bit old, but perhaps it will help someone. This one line solution worked for me

gridTAV.DataSource = dTAV.Values.ToList<TotalAccountValue>();

gridTAV is a DataGridView. dTAV is a Dictionary. The key is a date (not important), and the value is a class.

Dictionary<DateTime, TotalAccountValue> dTAV = new Dictionary<DateTime, TotalAccountValue>();

Since the value was a class the "ToArray()" method did not work for me, since it didn't "unpack" the class properties.

Note that this does not place the KEY in the grid, but I didn't really need that.

Binding Dictionary To Datagridview

You could use your Dictionary with the following Linq:

 dataGridView.DataSource =  (from d in dictionary
orderby d.Value
select new
{
d.Key,
d.Value
}).ToList();

This will create an anonymous object that will hold your Key and Value as properties. Be aware that the dictionary is by default not in a particular order.



Related Topics



Leave a reply



Submit