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

УдалитьAll для ObservableCollections?

Я ищу способ Linq (например, метод RemoveAll для List), который может удалить выбранные элементы из моего ObservableCollection.

Я слишком новичок в создании метода расширения для себя. Есть ли способ удалить элементы из ObservableCollection, передавая выражение Lambda?

4b9b3361

Ответ 1

Я не знаю, как удалить только выбранные элементы. Но создание метода расширения прямолинейно:

public static class ExtensionMethods
{
    public static int Remove<T>(
        this ObservableCollection<T> coll, Func<T, bool> condition)
    {
        var itemsToRemove = coll.Where(condition).ToList();

        foreach (var itemToRemove in itemsToRemove)
        {
            coll.Remove(itemToRemove);
        }

        return itemsToRemove.Count;
    }
}

Это удаляет все элементы из ObservableCollection, которые соответствуют условию. Вы можете так называть:

var c = new ObservableCollection<SelectableItem>();
c.Remove(x => x.IsSelected);

Ответ 2

Итерация назад должна быть более эффективной, чем создание временной коллекции, как в примере Даниэля Хильгарта.

public static class ObservableCollectionExtensions
{
    public static void RemoveAll<T>(this ObservableCollection<T> collection,
                                                       Func<T, bool> condition)
    {
        for (int i = collection.Count - 1; i >= 0; i--)
        {
            if (condition(collection[i]))
            {
                collection.RemoveAt(i);
            }
        }
    }
}

Ответ 3

Как насчет этой реализации для одного слоя?

observableCollection.Where(l => l.type == invalid).ToList().All(i => observableCollection.Remove(i))

- Изменить -

Извините, да, вам нужен ToList() в середине, чтобы заставить первую половину оценить, поскольку LINQ по умолчанию выполняет ленивую оценку.

Ответ 4

Каждое предлагаемое здесь решение, которое использует процедуру для удаления элемента один за другим, имеет одну ошибку. Представьте, что у вас много предметов в наблюдаемой коллекции, скажем 10.000 предметов. Затем вы хотите удалить элементы, которые удовлетворяют некоторому условию.

Если вы используете решение из Daniel Hilgarth и вызываете: c.Remove(x => x.IsSelected);, и, например, 3000 элементов будут удалены, предлагаемое решение сообщит об удалении каждого элемента. Это связано с тем, что внутренняя реализация Remove(item) уведомляет об этом изменении. И это будет вызвано для каждого из 3000 элементов в процессе удаления.

Итак, вместо этого я создал потомка ObservableCollection и добавил новый метод RemoveAll(predicate)

[Serializable]
public class ObservableCollectionExt<T> : ObservableCollection<T>
{
    public void RemoveAll(Predicate<T> predicate)
    {
        CheckReentrancy();

        List<T> itemsToRemove = Items.Where(x => predicate(x)).ToList();
        itemsToRemove.ForEach(item => Items.Remove(item));

        OnPropertyChanged(new PropertyChangedEventArgs("Count"));
        OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }
}

Интересная строка itemsToRemove.ForEach(item => Items.Remove(item));. Вызов напрямую Items.Remove(item) не будет уведомлять об удалении элемента.

Вместо удаления необходимых элементов изменения сообщаются сразу же по вызовам:

OnPropertyChanged(new PropertyChangedEventArgs("Count"));
OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));

Ответ 5

Невозможно передать выражение ObservableCollection, чтобы удалить соответствующие элементы, так же, как и общий список. ObservableCollection добавляет и удаляет по одному элементу за раз.

Вам нужно будет создать свою собственную реализацию INotifyCollectionChanged, или, как вы заметите, создайте метод расширения.

Ответ 6

Это моя версия решения метода расширения, которое является лишь небольшим изменением принятого ответа, но имеет то преимущество, что возвращенный счет основан на подтвержденном удалении элемента из коллекции:

public static class ObservableCollectionExtensionMethods
{
    /// <summary>
    /// Extends ObservableCollection adding a RemoveAll method to remove elements based on a boolean condition function
    /// </summary>
    /// <typeparam name="T">The type contained by the collection</typeparam>
    /// <param name="observableCollection">The ObservableCollection</param>
    /// <param name="condition">A function that evaluates to true for elements that should be removed</param>
    /// <returns>The number of elements removed</returns>
    public static int RemoveAll<T>(this ObservableCollection<T> observableCollection, Func<T, bool> condition)
    {
        // Find all elements satisfying the condition, i.e. that will be removed
        var toRemove = observableCollection
            .Where(condition)
            .ToList();

        // Remove the elements from the original collection, using the Count method to iterate through the list, 
        // incrementing the count whenever there a successful removal
        return toRemove.Count(observableCollection.Remove);
    }
}