7
votes

Observdictionner pour C #

J'essaie d'utiliser la suivi de la mise en œuvre de l'observation de l'observation: Observexdictionner (C #) .

Lorsque j'utilise le code suivant en liant le dictionnaire à un Datagramrid: P>

private void OnCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair<TKey, TValue> newItem, KeyValuePair<TKey, TValue> oldItem)
{
  OnPropertyChanged();

  if (CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, newItem, oldItem));
}


1 commentaires

5 Réponses :


7
votes

Structure de données similaire, pour se lier à la collection type de dictionnaire

http: / /drwpf.com/blog/2007/09/16/CAN-IMTIND-MY-ITEMSCONTROL-A-A-Dictionary/

Il fournit une nouvelle structure de données observée et incendie Propertyhanged en cas de changement au dictionnaire sous-jacent.


0 commentaires

10
votes

Voici ce que j'ai fait à la fin:

[Serializable]
public class ObservableKeyValuePair<TKey,TValue>:INotifyPropertyChanged
{
    #region properties
    private TKey key;
    private TValue value;

    public TKey Key
    {
        get { return key; }
        set
        {
            key = value;
            OnPropertyChanged("Key");
        }
    }

    public TValue Value
    {
        get { return value; }
        set
        {
            this.value = value;
            OnPropertyChanged("Value");
        }
    } 
    #endregion

    #region INotifyPropertyChanged Members

    [field:NonSerialized]
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(name));
    }

    #endregion
}

[Serializable]
public class ObservableDictionary<TKey,TValue>:ObservableCollection<ObservableKeyValuePair<TKey,TValue>>, IDictionary<TKey,TValue>
{

    #region IDictionary<TKey,TValue> Members

    public void Add(TKey key, TValue value)
    {
        if (ContainsKey(key))
        {
            throw new ArgumentException("The dictionary already contains the key");
        }
        base.Add(new ObservableKeyValuePair<TKey, TValue>() {Key = key, Value = value});
    }

    public bool ContainsKey(TKey key)
    {
        //var m=base.FirstOrDefault((i) => i.Key == key);
        var r = ThisAsCollection().FirstOrDefault((i) => Equals(key, i.Key));

        return !Equals(default(ObservableKeyValuePair<TKey, TValue>), r);
    }

    bool Equals<TKey>(TKey a, TKey b)
    {
        return EqualityComparer<TKey>.Default.Equals(a, b);
    }

    private ObservableCollection<ObservableKeyValuePair<TKey, TValue>> ThisAsCollection()
    {
        return this;
    }

    public ICollection<TKey> Keys
    {
        get { return (from i in ThisAsCollection() select i.Key).ToList(); }
    }

    public bool Remove(TKey key)
    {
        var remove = ThisAsCollection().Where(pair => Equals(key, pair.Key)).ToList();
        foreach (var pair in remove)
        {
            ThisAsCollection().Remove(pair);
        }
        return remove.Count > 0;
    }

    public bool TryGetValue(TKey key, out TValue value)
    {
        value = default(TValue);
        var r = GetKvpByTheKey(key);
        if (!Equals(r, default(ObservableKeyValuePair<TKey, TValue>)))
        {
            return false;
        }
        value = r.Value;
        return true;
    }

    private ObservableKeyValuePair<TKey, TValue> GetKvpByTheKey(TKey key)
    {
        return ThisAsCollection().FirstOrDefault((i) => i.Key.Equals(key));
    }

    public ICollection<TValue> Values
    {
        get { return (from i in ThisAsCollection() select i.Value).ToList(); }
    }

    public TValue this[TKey key]
    {
        get
        {
            TValue result;
            if (!TryGetValue(key,out result))
            {
                throw new ArgumentException("Key not found");
            }
            return result;
        }
        set
        {
            if (ContainsKey(key))
            {
                GetKvpByTheKey(key).Value = value;
            }
            else
            {
                Add(key, value);
            }
        }
    }

    #endregion

    #region ICollection<KeyValuePair<TKey,TValue>> Members

    public void Add(KeyValuePair<TKey, TValue> item)
    {
        Add(item.Key, item.Value);
    }

    public bool Contains(KeyValuePair<TKey, TValue> item)
    {
        var r = GetKvpByTheKey(item.Key);
        if (Equals(r, default(ObservableKeyValuePair<TKey, TValue>)))
        {
            return false;
        }
        return Equals(r.Value, item.Value);
    }

    public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
    {
        throw new NotImplementedException();
    }

    public bool IsReadOnly
    {
        get { return false; }
    }

    public bool Remove(KeyValuePair<TKey, TValue> item)
    {
        var r = GetKvpByTheKey(item.Key);
        if (Equals(r, default(ObservableKeyValuePair<TKey, TValue>)))
        {
            return false;
        }
        if (!Equals(r.Value,item.Value))
        {
            return false ;
        }
        return ThisAsCollection().Remove(r);
    }

    #endregion

    #region IEnumerable<KeyValuePair<TKey,TValue>> Members

    public new IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
    {
        return (from i in ThisAsCollection() select new KeyValuePair<TKey, TValue>(i.Key, i.Value)).ToList().GetEnumerator();
    }

    #endregion
}


2 commentaires

IMO, ce n'est pas bon (pour les grandes données), car le but principal du dictionnaire est de ne pas stocker, mais de récupérer rapidement la récupération à l'aide de techniques de hachage. Ce lien A véritable observateur avec récupération rapide. (comme enveloppe observictionnaires sur le dictionnaire)


Bon travail! Dans trygetvalue , l'instruction IF doit être si (égale (R, défaut (ObservableKeyValuePair )))



-2
votes

Même j'utilise l'observateur de Github, j'ai également fait face à cette exception. J'avais déclaré la variable du dictionnaire au niveau de la classe plus tard, j'ai essayé de créer une nouvelle instance dans la méthode où il a été accédé.

OldCode qui a donné une exception: P>

public void MethodName()
{
    ObservableDictionary<string, string> _localVariableDictionary = new ObservableDictionary<string, string>();
}


0 commentaires


1
votes

J'ai fini par écrire une classe pour contenir la paire de valeur de clé et utiliser une collection de cette classe. J'utilise Caliburn Micro, où vient la liablecolection, mais une observablecollection devrait fonctionner de la même manière. J'utilise le motif MVVM.

la vue Mododel p> xxx pré>

le keyvaluepair personnalisé p> xxx pré>

et dans la vue P>

<ItemsControl ItemsSource="{Binding Items}">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <Grid>
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="*" />
          <ColumnDefinition Width="2*" />
          <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>

        <TextBox Grid.Column="0"
                 Text="{Binding Key, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        <TextBox Grid.Column="1"
                 Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
      </Grid>
    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>


0 commentaires