0

インデクサーを使用したObservableCollectionの.NETC#構文は何ですか?ObservableColletionが欲しいのですが、序数位置または文字列名でアイテムを参照します。これを使用してインデクサーを示すことは知っていますが、ObservableCollectionに配置する方法がわかりません。ありがとう

4つの答えをありがとう。私はcreateとObservableCollectionの方法を知っており、インデクサーの作成方法も知っています。それらを組み合わせる方法がわかりません。序数と文字列のインデックスを持つObservableCollectionのサンプルコードを求めています。もう一度ありがとう

4

4 に答える 4

3

ObservableCollectionはCollectionを継承しているため、すでに位置ベースのインデックスが作成されています。

文字列ベースのインデックス作成の場合、ObservableDictionaryの人々の実装を調べることができます。

個人的には、パフォーマンスを向上させるために、ObservableCollectionから派生したHashedObservableCollectionを作成しました。これには、ルックアップ時間を短縮するためのインデックスへのキーのディクショナリが含まれています。InsertItem、RemoveItem、およびClearItemsをオーバーライドすることにより、辞書の同期を維持します。

私の例では、キーはどのタイプでもかまいませんが、キーは変更されないと想定しています。アイテムが置き換えられると、同じキーを持つオブジェクトに置き換えられます。これを単純化したい場合は、TKeyをStringに置き換えることができます。

コード:

using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace foson.Utils
{
    /// <summary>
    /// Represents BindableCollection indexed by a dictionary to improve lookup/replace performance.
    /// </summary>
    /// <remarks>
    /// Assumes that the key will not change and is unique for each element in the collection.
    /// Collection is not thread-safe, so calls should be made single-threaded.
    /// </remarks>
    /// <typeparam name="TValue">The type of elements contained in the BindableCollection</typeparam>
    /// <typeparam name="TKey">The type of the indexing key</typeparam>
    public class HashedBindableCollection<TValue, TKey> : ObservableCollection<TValue>
    {

        protected internal Dictionary<TKey, int> indecies = new Dictionary<TKey, int>();
        protected internal Func<TValue, TKey> _keySelector;

        /// <summary>
        /// Create new HashedBindableCollection
        /// </summary>
        /// <param name="keySelector">Selector function to create key from value</param>
        public HashedBindableCollection(Func<TValue, TKey> keySelector)
            : base()
        {
            if (keySelector == null) throw new ArgumentException("keySelector");
            _keySelector = keySelector;
        }

        #region Protected Methods
        protected override void InsertItem(int index, TValue item)
        {
            var key = _keySelector(item);
            if (indecies.ContainsKey(key))
                throw new DuplicateKeyException(key.ToString());

            if (index != this.Count)
            {
                foreach (var k in indecies.Keys.Where(k => indecies[k] >= index).ToList())
                {
                    indecies[k]++;
                }
            }

            base.InsertItem(index, item);
            indecies[key] = index;

        }

        protected override void ClearItems()
        {
            base.ClearItems();
            indecies.Clear();
        }


        protected override void RemoveItem(int index)
        {
            var item = this[index];
            var key = _keySelector(item);

            base.RemoveItem(index);

            indecies.Remove(key);

            foreach (var k in indecies.Keys.Where(k => indecies[k] > index).ToList())
            {
                indecies[k]--;
            }
        }
        #endregion

        public virtual bool ContainsKey(TKey key)
        {
            return indecies.ContainsKey(key);
        }

        /// <summary>
        /// Gets or sets the element with the specified key.  If setting a new value, new value must have same key.
        /// </summary>
        /// <param name="key">Key of element to replace</param>
        /// <returns></returns>
        public virtual TValue this[TKey key]
        {

            get { return this[indecies[key]]; }
            set
            {
                //confirm key matches
                if (!_keySelector(value).Equals(key))
                    throw new InvalidOperationException("Key of new value does not match");

                if (!indecies.ContainsKey(key))
                {
                    this.Add(value);
                }
                else
                {
                    this[indecies[key]] = value;
                }
            }
        }

        /// <summary>
        /// Replaces element at given key with new value.  New value must have same key.
        /// </summary>
        /// <param name="key">Key of element to replace</param>
        /// <param name="value">New value</param>
        /// 
        /// <exception cref="InvalidOperationException"></exception>
        /// <returns>False if key not found</returns>
        public virtual bool Replace(TKey key, TValue value)
        {
            if (!indecies.ContainsKey(key)) return false;
            //confirm key matches
            if (!_keySelector(value).Equals(key))
                throw new InvalidOperationException("Key of new value does not match");

            this[indecies[key]] = value;
            return true;

        }

        public virtual bool Remove(TKey key)
        {
            if (!indecies.ContainsKey(key)) return false;

            this.RemoveAt(indecies[key]);
            return true;

        }

    }
    public class DuplicateKeyException : Exception
    {

        public string Key { get; private set; }
        public DuplicateKeyException(string key)
            : base("Attempted to insert duplicate key " + key + " in collection")
        {
            Key = key;
        }
    }
}
于 2011-11-16T19:17:08.233 に答える
2

これが私の考えです、これがあなたの解決策を見つけるのに役立つことを願っています

using System.Collections.ObjectModel;

namespace WPFValidation
{
  public class CustomObservableCollection<T> : ObservableCollection<T>
  {
    public T this[string key] {
      get {
        // you must implement some code to do this one
        T item = GetItemWithAKey(key);
        return item;
      }
      set {
        T item = GetItemWithAKey(key);
        if (item != null) {
          // set the given value toi the item
          this.SetItemValue(item, value);
        }
      }
    }

    private T GetItemWithAKey(string key) {
      // find the item with teh given key
      return default(T);
    }
  }

  public class TestClass
  {
    public TestClass() {
      var coll = new CustomObservableCollection<CustomKeyedClass>();
      coll.Add(new CustomKeyedClass("One"));
      coll.Add(new CustomKeyedClass("Two"));
      var item = coll["One"];
      var item2 = coll[1];
    }
  }
}
于 2011-11-16T20:01:50.070 に答える
0

私があなたの質問を正しく理解しているなら、あなたはこの例を使うことができます

http://msdn.microsoft.com/en-us/library/ms132434.aspx

于 2011-11-16T19:14:20.560 に答える
0

これがあなたが探している構文だと思います:

  //  create a generic ObservableCollection  - I used object, but you can use any Type
  var collection = new ObservableCollection<object>();

  //  set the item at the index.  
  collection[0] = new object();

ドキュメントObservableCollection<T>: http: //msdn.microsoft.com/en-us/library/ms668604.aspx

インデクサーのドキュメント(別名「Item」プロパティ):http://msdn.microsoft.com/en-us/library/ms132434.aspx

ObservableDictionaryあなたのコメントに基づいて、あなたはではなくを探しているように聞こえますObservableCollection。.NETにはそのようなコレクションが組み込まれていませんが、グーグルですばやく検索すると、次の2つの実装が見つかりました。

于 2011-11-16T19:14:51.123 に答える