我有一个包含商品和价格的Dictionary
。这些项目是唯一的,但是会在应用程序的整个生命周期内慢慢添加和更新(也就是说,我事先不知道这些项目字符串)。我想将此结构绑定(bind)到DataGridView,以便可以在Form上显示更新,例如:
Dictionary<string, double> _priceData = new Dictionary<string, double>();
BindingSource _bindingSource = new BindingSource();
dataGridView1.DataSource = _bindingSource;
_bindingSource.DataSource = _priceData;
但是不能,因为
Dictionary
不实现IList
(或IListSource
,IBindingList
或IBindingListView
)。有没有办法做到这一点?我需要保留唯一的商品列表,还需要更新现有商品的价格,因此
Dictionary
是我认为理想的数据结构,但我找不到在表单上显示数据的方法。更新:
Marc在下面的建议非常有效,但是我仍然不确定如何在执行过程中更新DataGridView。
我有一个类级变量:
private DictionaryBindingList<string, decimal> bList;
然后在
Main()
中实例化它:bList = new DictionaryBindingList<string,decimal>(prices);
dgv.DataSource = bList;
然后在程序执行过程中,如果有新条目添加到字典中:
prices.Add("foobar", 234.56M); bList.ResetBindings();
我以为那会刷新DataGridView。为什么不?
最佳答案
Dictionary
有几个问题;第一个是(如您所发现的)它没有实现必要的IList
/IListSource
。第二个原因是,没有对项目的保证顺序(实际上,也没有索引器),这使得无法通过索引(而不是键)进行随机访问。
但是...可能有些烟和镜子是可行的。如下所示:
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();
}
}
}
}
请注意,自定义扩展方法的使用完全是可选的,并且可以通过仅使用
new DictionaryBindingList<string,decimal>(prices)
在C#2.0等中删除。关于c# - 绑定(bind)到字典的DataGridView,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15246131/