简体   繁体   English

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

[英]C# Winforms Dictionary DataGrid Binding Auto-Refresh Without Losing Focus

Setup 设定

  • C# WinForms Application. C#WinForms应用程序。

Summary 摘要

  • Binding a dictionary to a datagridview. 将字典绑定到datagridview。
  • Updating the dictionary automatically updates the datagrid. 更新字典会自动更新数据网格。
  • The datagrid does not lose focus when the update happens. 更新发生时,数据网格不会失去焦点。
  • The binding works both ways (editing values in the grid updates the dictionary. 绑定以两种方式起作用(在网格中编辑值会更新字典。

Scenario 情境

  • I have a class that calculates values based on data from a database. 我有一个基于数据库中的数据计算值的类。
  • The data in this database constantly changes so hence, the calculated values change too. 该数据库中的数据不断变化,因此计算值也随之变化。
  • These calculated values are added to the properties of a custom object "MyCustomObject". 这些计算值将添加到自定义对象“ MyCustomObject”的属性中。
  • Each "MyCustomObject" is then added to a dictionary (or the custom object is updated if it already exists). 然后,将每个“ MyCustomObject”添加到词典中(或者如果自定义对象已经存在,则对其进行更新)。
  • The Dictionary is bound to a datagrid. 字典绑定到数据网格。

The idea 这个主意

  • The idea is that the calculated vales continually change and thus update the dictionary which in turn updates the datagrid. 这个想法是,计算的价位不断变化,因此更新了字典,字典又更新了数据网格。
  • Users who are interacting with the datagrid need to be able to see these changes automatically. 与数据网格进行交互的用户需要能够自动查看这些更改。
  • It is imperative that the currently selected row in the datagrid does not lose focus when the grid is updated with the new custom object values. 当使用新的自定义对象值更新网格时,必须确保数据网格中当前选定的行不会失去焦点。
  • The binding must work both ways (editing values in the grid updates the dictionary too. 绑定必须同时起作用(在网格中编辑值也会更新字典。

Question

  • How can I implement this automatic binding so that I get the requirements that I need? 如何实现此自动绑定,以便获得所需的要求?
  • I have already written the code to do all of the calculations and add/update the dictionary of MyCustomObjects. 我已经编写了执行所有计算并添加/更新MyCustomObjects字典的代码。
  • Examples of how to implement this datagrid binding would be greatly appreciated. 如何实现此数据网格绑定的示例将不胜感激。

In order to accomplish this, your Dictionary would need to implement IBindingList and fire the ListChanged event whenever changes were made. 为了完成此操作,您的Dictionary将需要实现IBindingListListChanged更改时触发ListChanged事件。 Here's a sample ( very ) barebones implementation of IDictionary<TKey, TValue> that also implements IBindingList : 这是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); }
}

Unfortunately, the selected row may or may not change, depending on which grid you're using. 不幸的是,所选行可能会更改,也可能不会更改,具体取决于您所使用的网格。 Your best bet is to save off the key of the selected row whenever it changes, then reselect that row (if present) when the dictionary is updated. 最好的选择是,只要更改了所选行的键,便会保留该键,然后在更新字典时重新选择该行(如果存在)。 Otherwise, there's no way to guarantee that you'll maintain the selection. 否则,无法保证您将保持选择。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM