【问题标题】:.NET 4.0 Indexer with ObservableCollection.NET 4.0 索引器与 ObservableCollection
【发布时间】:2011-12-30 17:23:42
【问题描述】:

带有索引器的 ObservableCollection 的 .NET C# 语法是什么?我想要一个 ObservableColletion 并按序号位置或字符串名称引用项目。我知道您使用它来表示索引器,但我不知道如何将它放入 ObservableCollection。谢谢

感谢您的 4 个回答。我知道如何创建和 ObservableCollection,并且我知道如何创建索引器。我不知道如何将它们结合起来。我要求提供带有序号和字符串索引的 ObservableCollection 的示例代码。 再次感谢

【问题讨论】:

    标签: .net observablecollection indexer


    【解决方案1】:

    如果我正确理解你的问题,你可以使用这个例子

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

    【讨论】:

      【解决方案2】:

      我认为这是您正在寻找的语法:

        //  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&lt;T&gt; 的文档:http://msdn.microsoft.com/en-us/library/ms668604.aspx

      索引器的文档(又名“Item”属性):http://msdn.microsoft.com/en-us/library/ms132434.aspx

      根据您的 cmets,听起来您正在寻找 ObservableDictionary 而不是 ObservableCollection。 .NET 没有内置这样的集合,但通过谷歌快速搜索发现了这两个实现:

      【讨论】:

      • 该链接是集合的序号索引。问题是带有序号和字符串索引的 ObservableCollection 的 C# 语法。
      • @BalamBalam,ObservableCollection 类未按字符串值索引。您需要维护一个字符串数组,其索引对应于可观察集合的索引。
      • ObservableDictionary 是个好名字,希望 .NET 在未来的版本中会有一个。
      【解决方案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;
              }
          }
      }
      

      【讨论】:

      • 我需要更多细节。带有序数和字符串索引的 ObservableCollection 的 C# 语法。
      • 看看public virtual TValue this[TKey key] 方法。只要每个重载具有不同的参数类型,您就可以多次重载索引器函数 (public XXX this[YYY])。
      • 太棒了!真的很喜欢那个构造函数。我认为序数部分是通过从 ObservableCollection 继承来处理的?
      【解决方案4】:

      这是我的想法,希望这有助于找到您的解决方案

      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];
          }
        }
      }
      

      【讨论】:

      • GetItemsWithKey 是我绘制空白的地方。 +1 foson 的答案是我需要的一切(我认为)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-27
      • 1970-01-01
      • 2011-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多