我该如何更新ObservableCollection类中的单个项?
我知道如何添加。我也知道如何在“for”循环中逐一搜索ObservableCollection中的项(使用Count表示项的数量),但是我如何更改现有项。如果我使用“foreach”找到需要更新的项,那么我如何将其放回ObservableCollection中?
我该如何更新ObservableCollection类中的单个项?
我知道如何添加。我也知道如何在“for”循环中逐一搜索ObservableCollection中的项(使用Count表示项的数量),但是我如何更改现有项。如果我使用“foreach”找到需要更新的项,那么我如何将其放回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
事件(理想情况下,如果你拥有接口,它应该在所有公共属性上实现,但从功能上来说,只有你将要更新的属性才真正重要)。found = newObject
,但是没有起作用。这一定意味着 FirstOrDefault
返回了一个重复的对象实例。你使用 IndexOf
获取真正的实例的解决方案对我很有帮助。 - JKennedyFirstOrDefault
并没有复制实例本身。如果您修改该实例上的属性,则会在所有地方更改它。局部变量found
只是一个引用,例如,“该实例位于[内存位置]123”。集合还有一些东西也说“该实例位于123”。如果您将found
更改为读取“该实例位于434”,则集合仍然有一些东西说“该实例位于123”。 - Tim S.您无需删除元素,然后进行更改和添加。您可以简单地使用LINQ FirstOrDefault
方法,通过适当的谓词查找必要的项并更改其属性,例如:
var item = list.FirstOrDefault(i => i.Name == "John");
if (item != null)
{
item.LastName = "Smith";
}
从ObservableCollection
中移除或添加项目将生成CollectionChanged
事件。
这是一些基于Collection类的扩展方法示例,参考Tim S's examples:
FirstOrDefault
的C#示例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
的VB<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
struct
或另一个值类型,则必须删除旧值并添加新值。