如何更新ObservableCollection类中的单个项

本文关键字:单个项 ObservableCollection 何更新 更新 | 更新日期: 2023-09-27 18:02:57

如何更新ObservableCollection类中的单个项目?

我知道如何做一个添加。我知道如何搜索ObservableCollection一个项目在一次"for"循环(使用计数作为项目数量的表示),但我如何改变现有的项目。如果我做一个"foreach"并找到需要更新的项目,我如何把它放回ObservableCollection>

如何更新ObservableCollection类中的单个项

您通常不能更改正在迭代的集合(使用foreach)。当然,解决这个问题的方法是,当你改变它时,不要对它进行迭代。(x.Id == myId和LINQ FirstOrDefault是您的标准/搜索的占位符,重要的部分是您已经获得了对象和/或对象的索引)

for (int i = 0; i < theCollection.Count; i++) {
  if (theCollection[i].Id == myId)
    theCollection[i] = newObject;
}

var found = theCollection.FirstOrDefault(x=>x.Id == myId);
int i = theCollection.IndexOf(found);
theCollection[i] = newObject;

var found = theCollection.FirstOrDefault(x=>x.Id == myId);
theCollection.Remove(found);
theCollection.Add(newObject);

var found = theCollection.FirstOrDefault(x=>x.Id == myId);
found.SomeProperty = newValue;

如果最后一个例子可以,你真正需要知道的是如何让观察你的ObservableCollection的东西意识到变化,你应该在对象的类上实现INotifyPropertyChanged,并确保在你正在改变的属性发生变化时引发PropertyChanged(理想情况下,如果你有接口,它应该在所有公共属性上实现,但在功能上当然它真的只对你要更新的属性重要)。

您不需要删除项目,更改,然后添加。您可以简单地使用LINQ FirstOrDefault方法使用适当的谓词找到所需的项目并更改其属性,例如:

var item = list.FirstOrDefault(i => i.Name == "John");
if (item != null)
{
    item.LastName = "Smith";
}

删除或添加ObservableCollection项将生成CollectionChanged事件

下面是Tim S的示例,作为Collection类之上的扩展方法:

CS with FirstOrDefault

public static void ReplaceItem<T>(this Collection<T> col, Func<T, bool> match, T newItem)
{
    var oldItem = col.FirstOrDefault(i => match(i));
    var oldIndex = col.IndexOf(oldItem);
    col[oldIndex] = newItem;
}

CS with Indexed Loop

public static void ReplaceItem<T>(this Collection<T> col, Func<T, bool> match, T newItem)
{
    for (int i = 0; i <= col.Count - 1; i++)
    {
        if (match(col[i]))
        {
            col[i] = newItem;
            break;
        }
    }
}
使用

假设你有这样的类设置

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}

您可以像这样调用以下函数/实现之一,其中match参数用于标识您想要替换的项目:

var people = new Collection<Person>
{
    new Person() { Id = 1, Name = "Kyle"},
    new Person() { Id = 2, Name = "Mit"}
};
people.ReplaceItem(x => x.Id == 2, new Person() { Id = 3, Name = "New Person" });

VB与索引循环

<Extension()>
Public Sub ReplaceItem(Of T)(col As Collection(Of T), match As Func(Of T, Boolean), newItem As T)
    For i = 0 To col.Count - 1
        If match(col(i)) Then
            col(i) = newItem
            Exit For
        End If
    Next
End Sub  

VB with FirstOrDefault

<Extension()>
Public Sub ReplaceItem(Of T)(col As Collection(Of T), match As Func(Of T, Boolean), newItem As T)
    Dim oldItem = col.FirstOrDefault(Function(i) match(i))
    Dim oldIndex = col.IndexOf(oldItem)
    col(oldIndex) = newItem      
End Sub

这取决于它是什么类型的对象

如果它是一个普通的c#类,只需更改对象的属性。你不需要对藏品做任何改动。集合保存对对象的引用,即使对象的属性发生变化,该引用也是相同的。对象的更改不会触发集合本身的更改通知,因为集合并没有真正更改,只是其中的一个对象更改了。

如果它是不可变的c#类(如string), struct或其他值类型,则必须删除旧值并添加新值