我有一个Dictionary包含商品和价格的商品。这些项目是唯一的,但是会在应用程序的整个生命周期内慢慢添加和更新(也就是说,我事先不知道这些项目字符串)。我想将此结构绑定到DataGridView,以便可以在Form上显示更新,例如:
Dictionary
Dictionary<string, double> _priceData = new Dictionary<string, double>(); BindingSource _bindingSource = new BindingSource(); dataGridView1.DataSource = _bindingSource; _bindingSource.DataSource = _priceData;
但不能,因为Dictionary没有实现IList(或IListSource,IBindingList或IBindingListView)。
IList
IListSource
IBindingList
IBindingListView
有没有办法做到这一点?我需要保留一个唯一的商品列表,还需要更新现有商品的价格,因此Dictionary我认为是理想的数据结构,但是我找不到在表单上显示数据的方法。
更新:
Marc的以下建议非常有效,但是我仍然不确定执行期间如何更新DataGridView。
我有一个类级变量:
private DictionaryBindingList<string, decimal> bList;
然后在中实例化它Main():
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(); } } } }
请注意,自定义扩展方法的使用完全是可选的,并且可以在C#2.0等中通过仅使用new DictionaryBindingList<string,decimal>(prices)来删除。
new DictionaryBindingList<string,decimal>(prices)