C#Winforms字典DataGrid绑定自动刷新而不会丢失焦点

时间:2010-07-15 12:38:36

标签: c# winforms data-binding datagrid

设置

  • C#WinForms Application。

摘要

  • 将字典绑定到datagridview。
  • 更新字典会自动更新数据网格。
  • 更新发生时,数据网格不会失去焦点。
  • 绑定有两种方式(网格中的编辑值会更新字典。

方案

  • 我有一个计算值的类 基于数据库中的数据。
  • 此数据库中的数据不断变化,因此计算值也会发生变化。
  • 这些计算值将添加到自定义对象“MyCustomObject”的属性中。
  • 然后将每个“MyCustomObject”添加到字典中(如果自定义对象已存在,则更新自定义对象)。
  • 字典绑定到数据网格。

想法

  • 这个想法是计算出来的值不断变化,从而更新字典,而字典又会更新数据网格。
  • 与数据网格交互的用户需要能够自动查看这些更改。
  • 当使用新的自定义对象值更新网格时,数据网格中当前选定的行必须不会失去焦点。
  • 绑定必须双向工作(网格中的编辑值也会更新字典。

问题

  • 如何实现此自动绑定,以便获得我需要的要求?
  • 我已编写代码来执行所有计算并添加/更新MyCustomObjects的字典。
  • 非常感谢如何实现此数据网格绑定的示例。

1 个答案:

答案 0 :(得分:1)

为了实现这一目标,您的词典需要实施IBindingList并在发生更改时触发ListChanged事件。以下是IDictionary<TKey, TValue>的示例(非常)准分子实现,它还实现了IBindingList

public class BindableDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IBindingList
{
    private Dictionary<TKey, TValue> source = new Dictionary<TKey, TValue>();

    void IBindingList.AddIndex(PropertyDescriptor property) { }
    object IBindingList.AddNew() { throw new NotImplementedException(); }
    bool IBindingList.AllowEdit { get { return false; } }
    bool IBindingList.AllowNew { get { return false; } }
    bool IBindingList.AllowRemove { get { return false; } }
    void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction) { }
    int IBindingList.Find(PropertyDescriptor property, object key) { throw new NotImplementedException(); }
    bool IBindingList.IsSorted { get { return false; } }
    void IBindingList.RemoveIndex(PropertyDescriptor property) { }
    void IBindingList.RemoveSort() { }
    ListSortDirection IBindingList.SortDirection { get { return ListSortDirection.Ascending; } }
    PropertyDescriptor IBindingList.SortProperty { get { return null; } }
    bool IBindingList.SupportsChangeNotification { get { return true; } }
    bool IBindingList.SupportsSearching { get { return false; } }
    bool IBindingList.SupportsSorting { get { return false; } }
    int System.Collections.IList.Add(object value) { throw new NotImplementedException(); }
    void System.Collections.IList.Clear() { Clear(); }
    bool System.Collections.IList.Contains(object value) { if (value is TKey) { return source.ContainsKey((TKey)value); } else if (value is TValue) { return source.ContainsValue((TValue)value); } return false; }
    int System.Collections.IList.IndexOf(object value) { return -1; }
    void System.Collections.IList.Insert(int index, object value) { throw new NotImplementedException(); }
    bool System.Collections.IList.IsFixedSize { get { return false; } }
    bool System.Collections.IList.IsReadOnly { get { return true; } }
    void System.Collections.IList.Remove(object value) { if (value is TKey) { Remove((TKey)value); } }
    void System.Collections.IList.RemoveAt(int index) { throw new NotImplementedException(); }
    object System.Collections.IList.this[int index] { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }

    private ListChangedEventHandler listChanged;

    event ListChangedEventHandler IBindingList.ListChanged
    {
        add { listChanged += value; }
        remove { listChanged -= value; }
    }

    protected virtual void OnListChanged(ListChangedEventArgs e)
    {
        var evt = listChanged;

        if (evt != null) evt(this, e);
    }

    public void Add(TKey key, TValue value)
    {
        source.Add(key, value);

        OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
    }

    public bool Remove(TKey key)
    {
        if (source.Remove(key))
        {
            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));

            return true;
        }

        return false;
    }

    public TValue this[TKey key]
    {
        get
        {
            return source[key];
        }
        set
        {
            source[key] = value;

            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }
    }

    void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
    {
        ((ICollection<KeyValuePair<TKey, TValue>>)source).Add(item);

        OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
    }

    bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
    {
        if (((ICollection<KeyValuePair<TKey, TValue>>)source).Remove(item))
        {
            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));

            return true;
        }

        return false;
    }

    public bool ContainsKey(TKey key) { return source.ContainsKey(key); }
    public ICollection<TKey> Keys { get { return source.Keys; } }
    public bool TryGetValue(TKey key, out TValue value) { return source.TryGetValue(key, out value); }
    public ICollection<TValue> Values { get { return source.Values; } }
    public void Clear() { source.Clear(); }
    bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item) { return ((ICollection<KeyValuePair<TKey, TValue>>)source).Contains(item); }
    void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) { ((ICollection<KeyValuePair<TKey, TValue>>)source).CopyTo(array, arrayIndex); }
    public int Count { get { return source.Count; } }
    bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly { get { return ((ICollection<KeyValuePair<TKey, TValue>>)source).IsReadOnly; } }
    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { return source.GetEnumerator(); }
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); }
    bool ICollection.IsSynchronized { get { return false; } }
    object ICollection.SyncRoot { get { return null; } }
    void ICollection.CopyTo(Array array, int arrayIndex) { ((ICollection)source).CopyTo(array,arrayIndex); }
}

不幸的是,根据您使用的网格,所选行可能会也可能不会更改。您最好的选择是在更改时保存所选行的键,然后在更新字典时重新选择该行(如果存在)。否则,无法保证您将保持选择。