Подтвердить что ты не робот

Как обновить один элемент в классе ObservableCollection?

Как обновить один элемент в классе ObservableCollection?

Я знаю, как сделать Add. И я знаю, как искать элемент ObservableCollection по одному элементу за раз в цикле "for" (используя Count в качестве представления элемента данных), но как я могу использовать существующий элемент. Если я делаю "foreach" и нахожу, какой элемент нуждается в обновлении, как вернуть его в ObservableCollection >

4b9b3361

Ответ 1

Вам не нужно удалять элемент, изменять, а затем добавлять. Вы можете просто использовать метод LINQ FirstOrDefault для поиска нужного элемента с использованием соответствующего предиката и изменения его свойств, например:

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

Удаление или добавление элемента в ObservableCollection приведет к событию CollectionChanged.

Ответ 2

Обычно вы не можете изменять коллекцию, через которую вы выполняете (через 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 когда изменяемое свойство изменяется (в идеале оно должно быть реализовано во всех общедоступных свойствах, если у вас есть интерфейс, но функционально, конечно, это действительно важно только для тех, которые вы будете обновлять).

Ответ 3

Вот примеры Тима S в качестве методов расширения поверх класса Collection:

CS с индексированной петлей

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 с FirstOrDefault

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

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 с 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

Ответ 4

Это зависит от типа объекта.

Если это обычный класс С#, просто измените свойства объекта. Вам не нужно ничего делать с коллекцией. В коллекции содержится ссылка на объект, который является таким же, даже если свойства объекта изменяются. Изменение объекта не вызовет уведомления об изменении самой коллекции, так как коллекция не изменилась, только один из объектов в ней.

Если это неизменный класс С# (например, строка), struct или другой тип значения, вы должны удалить старое значение и добавить новый.