带有索引器的 ObservableCollection 的 .NET C# 语法是什么?我想要一个 ObservableColletion 并按序号位置或字符串名称引用项目。我知道您使用它来表示索引器,但我不知道如何将它放入 ObservableCollection。谢谢
感谢您的4个答案。我知道如何创建和 ObservableCollection,也知道如何创建索引器。我不知道如何将它们结合起来。我要求提供带有序号和字符串索引的 ObservableCollection 的示例代码。再次感谢
带有索引器的 ObservableCollection 的 .NET C# 语法是什么?我想要一个 ObservableColletion 并按序号位置或字符串名称引用项目。我知道您使用它来表示索引器,但我不知道如何将它放入 ObservableCollection。谢谢
感谢您的4个答案。我知道如何创建和 ObservableCollection,也知道如何创建索引器。我不知道如何将它们结合起来。我要求提供带有序号和字符串索引的 ObservableCollection 的示例代码。再次感谢
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;
}
}
}
这是我的想法,希望这有助于找到您的解决方案
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];
}
}
}
我认为这是您正在寻找的语法:
// 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();
文档:http ObservableCollection<T>: //msdn.microsoft.com/en-us/library/ms668604.aspx
索引器的文档(又名“项目”属性):http: //msdn.microsoft.com/en-us/library/ms132434.aspx
根据您的评论,听起来您正在寻找一个ObservableDictionary而不是一个ObservableCollection. .NET 没有内置这样的集合,但通过谷歌快速搜索发现了这两个实现:
如果我正确理解你的问题,你可以使用这个例子