开发者

WPF - How can I implement an ObservableCollection<K,T> with a key (like a Dictionary)?

开发者 https://www.devze.com 2023-01-18 04:17 出处:网络
I have used an ObservableCollection with WPF for binding and this works well.What I really want at the moment is a Dictionary like one, that has a key that I can use, so effectively like \"ObservableC

I have used an ObservableCollection with WPF for binding and this works well. What I really want at the moment is a Dictionary like one, that has a key that I can use, so effectively like "ObservableCollection".

Can you suggest the code that could be us开发者_JAVA百科ed to provide such an ObservableCollection? The goal is to have a Dictionary like structure that I can bind to from WPF.

Thanks


Someone already made it. I haven't try it yet but nothing to lose.


How about:

var collection = new ObservableCollection<KeyValuePair<TKey, TValue>>();

You should be able to address it with:

collection.First(x => x.Key == *your key value*) .Key or .Value


Create a class that implements the IDictionary, INotifyCollectionChanged & INotifyPropertyChanged interfaces. The class would have an instance of Dictionary that it would use for the implementation of IDictionary (one of the Add methods is coded below as an example). Both INotifyCollectionChanged and INotifyProperyChanged require the presence of events, these events should be fired at appropriate points in the wrapper functions (again, consult the Add method below for an example)

class ObservableDictionary<TKey, TValue> : IDictionary, INotifyCollectionChanged, INotifyPropertyChanged
{
    private Dictionary<TKey, TValue> mDictionary;
    // Methods & Properties for IDictionary implementation would defer to mDictionary:
    public void Add(TKey key, TValue value){
        mDictionary.Add(key, value);
        OnCollectionChanged(NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, value)
        return;
    }
    // Implementation of INotifyCollectionChanged:
    public event NotifyCollectionChangedEventHandler CollectionChanged;
    protected void OnCollectionChanged(NotifyCollectionChangedEventArgs args){
        // event fire implementation
    }
    // Implementation of INotifyProperyChanged:
    public event ProperyChangedEventHandler ProperyChanged;
    protected void OnPropertyChanged(PropertyChangedEventArgs args){
        // event fire implementation
    }
}

Edit:

Note that an implementation of the IDictionary interface directly or indirectly would require that three additional interfaces be implemented:

ICollection<KeyValuePair<TKey,TValue>>
IEnumerable<KeyValuePair<TKey,TValue>>
IEnumerable.

Depending on your needs you may not have to implement the entire IDictionary interface, if you are only going to be calling a couple of the methods then just implement those methods and the IDictionary interface becomes a luxury. You must implement the INotifyCollectionChanged and INotifyPropertyChanged interfaces for binding to work however.Blockquote


What about something like :

ObservableCollection<Tuple<string, object>>()

where string and object and sample types of course


public class ObservableDictonary<TKey, TValue> : Dictionary<TKey, TValue>, INotifyCollectionChanged, INotifyPropertyChanged
{
    public event NotifyCollectionChangedEventHandler CollectionChanged;

    public event PropertyChangedEventHandler PropertyChanged;

    public new void Add(TKey key, TValue value)
    {
        base.Add(key, value);
        if (!TryGetValue(key, out _)) return;
        var index = Keys.Count;
        OnPropertyChanged(nameof(Count));
        OnPropertyChanged(nameof(Values));
        OnCollectionChanged(NotifyCollectionChangedAction.Add, value, index);
    }

    public new void Remove(TKey key)
    {
        if (!TryGetValue(key, out var value)) return;
        var index = IndexOf(Keys, key);
        OnPropertyChanged(nameof(Count));
        OnPropertyChanged(nameof(Values));
        OnCollectionChanged(NotifyCollectionChangedAction.Remove, value, index);
        base.Remove(key);
    }

    public new void Clear()
    {

    }

    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        PropertyChanged?.Invoke(this, e);
    }

    protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        CollectionChanged?.Invoke(this, e);
    }

    private void OnPropertyChanged(string propertyName)
    {
        OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
    }

    private void OnCollectionChanged(NotifyCollectionChangedAction action, object item)
    {
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item));
    }

    private void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index)
    {
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index));
    }

    private int IndexOf(KeyCollection keys, TKey key)
    {
        var index = 0;
        foreach (var k in keys)
        {
            if (Equals(k, key))
                return index;
            index++;
        }
        return -1;
    }
}

I override Add, Remove and Clear. You must understand, if you use extension method or simple method, which take Dictionary parameter, you will not see changing, because in this situation, Add or Remove method will use of Dictionary (not ObservableDictonary). So you must direct methods (Add or Remove) of ObservableDictonary

0

精彩评论

暂无评论...
验证码 换一张
取 消