如何更新ObservableCollection类中的单个项目?
我知道如何添加。我知道如何在“for”循环中一次搜索ObservableCollection一个项目(使用Count作为项目的表示)但是如何查找现有项目。如果我执行“foreach”并找到需要更新的项目,如何将其重新放入ObservableCollection>
答案 0 :(得分:37)
您无需删除项目,更改,然后添加。您可以简单地使用LINQ FirstOrDefault
方法使用适当的谓词查找必要的项目并更改其属性,例如:
var item = list.FirstOrDefault(i => i.Name == "John");
if (item != null)
{
item.LastName = "Smith";
}
删除或向ObservableCollection
添加项目会生成CollectionChanged
个事件。
答案 1 :(得分:32)
您通常无法更改正在迭代的集合(使用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
(理想情况下,如果你有接口,它应该在所有公共属性上实现,但功能上当然它只对你要更新的属性有用)。
答案 2 :(得分:5)
以下是Tim S's examples作为集合类顶部的扩展方法:
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;
}
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" });
<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
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
答案 3 :(得分:2)
这取决于它是什么类型的对象。
如果是普通的C#类,只需更改对象的属性即可。你不必为集合做任何事情。即使对象的属性发生更改,该集合仍保持对对象的引用。对象的更改不会触发集合本身的更改通知,因为集合实际上没有更改,只是其中一个对象。
如果它是不可变的C#类(例如字符串),struct
或其他值类型,则必须删除旧值并添加新值。