的DataGridView绑定到一个词典 [英] DataGridView bound to a Dictionary
问题描述
我有一个词典
包含项目和价格。该项目是独一无二的,但慢慢的添加,并通过应用程序生命周期更新(即我不知道项字符串提前)。我想这种结构绑定到一个DataGridView,这样我就可以证明我的表上的更新,是这样的:
I have a Dictionary
that contains items and prices. The items are unique but slowly get added and updated through the lifetime of the application (that is, I don't know the item strings in advance). I would like to bind this structure to a DataGridView, so I can show updates on my Form, something like:
Dictionary<string, double> _priceData = new Dictionary<string, double>();
BindingSource _bindingSource = new BindingSource();
dataGridView1.DataSource = _bindingSource;
_bindingSource.DataSource = _priceData;
但不能,因为词典
不执行的IList
(或 IListSource
, IBindingList的
或 IBindingListView
)。
But cannot, since Dictionary
does not implement IList
(or IListSource
, IBindingList
, or IBindingListView
).
有没有办法来实现这一目标?我需要保持项目的唯一列表,同时也更新了价格的现有项目,因此词典
是理想的数据结构我想,但我不能找到一种方法显示我的表上的数据。
Is there a way to achieve this? I need to keep a unique list of items, but also update the price for an existing item, so a Dictionary
is the ideal data structure I think, but I cannot find a way to display the data on my Form.
更新:
马克的建议,下面的作品非常漂亮,但我仍然不知道如何执行过程中更新的DataGridView。
Marc's suggestion below works very nicely, but I'm still not sure how to update the DataGridView during execution.
我有一个类级变量:
private DictionaryBindingList<string, decimal> bList;
然后实例,在主要()
:
bList = new DictionaryBindingList<string,decimal>(prices);
dgv.DataSource = bList;
程序执行期间然后,如果一个新的条目被添加到词典:
Then during program execution if a new entry is added to the dictionary:
prices.Add("foobar", 234.56M); bList.ResetBindings();
我认为这将刷新DataGridView的。为什么不呢?
I thought that would refresh the DataGridView. Why not?
推荐答案
有与词典
的几个问题;第一个是(如你发现)它不实施必要的的IList
/ IListSource
。第二个是,没有保证为了将产品(实际上,没有索引),从而使由索引随机访问(而不是通过键)是不可能的。
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();
}
}
}
}
请注意,使用自定义的扩展方法是完全可选的,并且可以去除在C#2.0等,只需使用新DictionaryBindingList&LT;字符串,小数&GT;(价格)
代替。
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.
这篇关于的DataGridView绑定到一个词典的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!