的DataGridView绑定到一个词典 [英] DataGridView bound to a Dictionary

查看:195
本文介绍了的DataGridView绑定到一个词典的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个词典包含项目和价格。该项目是独一无二的,但慢慢的添加,并通过应用程序生命周期更新(即我不知道项字符串提前)。我想这种结构绑定到一个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆