Могу ли я откатить изменения коллекции по событию изменения коллекции? - PullRequest
9 голосов
/ 25 декабря 2010

У меня есть 2 вида списка ... и кнопки добавления / удаления между ними.

При изменении события коллекции для коллекции списков-представлений в viewmodel, могу ли я откатить изменения для определенного условия?

Ответы [ 3 ]

5 голосов
/ 25 декабря 2010

Вы можете обработать событие CollectionChanged ObservableCollection для резервного копирования (через виртуальную машину или любую другую) старых значений (см. Свойство NotifyCollectionChangedEventArgs.OldItems) и их получения назад, когда это необходимо, т.е. когда пользователь нажимает «Отменить» и т. д.

Обновление По комментариям ниже:

Если вы хотите откатить коллекцию без использования обработчика событий CollectionChanged, создайте флаг, где вы экранируете обработчик от рекурсивного вызова (не тестировался в многопоточном приложении), вот простой пример может легко настроить его под ваш V / VM.

private void Window_Loaded(object sender, RoutedEventArgs e)
{
  var x = new ObservableCollection<string>();
  x.CollectionChanged += 
    new NotifyCollectionChangedEventHandler(x_CollectionChanged);
  x.Add("asdf");
  x.Remove("asdf");
}

bool rollingBack = false;
void x_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
  if (rollingBack) return;

  if (e.Action == NotifyCollectionChangedAction.Remove)
  {
    if (e.OldItems.Contains("asdf"))
    {
      var oc = (ObservableCollection<string>)sender;
      rollingBack = true;
      oc.Add("asdf");
      rollingBack = false;
    }
  }
}
1 голос
/ 25 декабря 2010

Учитывая, что вы получаете отправителя события как объект (т.е. первый параметр события) и список объектов, которые были изменены, да, вы можете сделать это. Я бы не советовал, хотя. Если вы сталкиваетесь с таким условием, предоставьте метод для ViewModel, который предоставляется с EventArgs, и позвольте ему делать свою работу. Представление не место для логики.

Еще лучше: проверьте условие в самой ViewModel (т.е. в командах, отвечающих за добавление / удаление)! Модель представления отвечает за состояние информации, поэтому придерживайтесь своей логики. Представление просто для отображения данных.

0 голосов
/ 11 мая 2015

Ответ Шимми не сработал для меня в приложении Магазина Windows, вы все равно столкнетесь с проблемами повторного входа и получите InvalidOperationException с надписью «Невозможно изменить ObservableCollection во время события CollectionChanged».

Мне пришлось использовать диспетчер пользовательского интерфейса и отключить / включить обработчик событий, чтобы избежать этих проблем.

Имейте в виду: это хак, и разработчики фреймворков пошли на многое, чтобы помешать вам сделать это.Поэтому, если вы хотите игнорировать их предупреждение, будьте осторожны, чтобы не выстрелить себе в ногу.

Items.CollectionChanged += ItemsChanged;

private async void ItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if(condition)
    {
        //rollback
        await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
            CoreDispatcherPriority.Normal, () => {

                //disable/enable event handler
                Items.CollectionChanged -= ItemsChanged;

                Items.Remove(e.NewItems[0]);

                Items.CollectionChanged += ItemsChanged;
            })).AsTask();
    }
}

Это позволит избежать исключения, избегать рекурсивного вызова обработчика и корректно обновлять пользовательский интерфейс.

...