9

我有 2 个列表视图...并在它们之间添加/删除按钮。

在视图模型中列表视图集合的集合更改事件中,我可以回滚特定条件的更改吗?

4

3 回答 3

5

您可以处理备份CollectionChanged事件ObservableCollection(通过 VM 或其他)旧值(参见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;
    }
  }
}
于 2010-12-25T17:02:29.270 回答
1

考虑到您将事件的发送者作为一个对象(即事件的第一个参数)和已修改的对象列表,是的,您可以这样做。不过我不建议这样做。如果遇到这种情况,请在 ViewModel 上提供一个方法,该方法与 一起提供EventArgs,并让它完成工作。视图不是做逻辑的地方。

更好的是:检查 ViewModel 本身的条件(即在可响应添加/删除的命令中)!视图模型对信息的状态是可响应的,因此请保留您的逻辑。视图只是用于显示数据。

于 2010-12-25T16:51:23.717 回答
0

Shimmy 的回答在 Windows 应用商店应用程序上对我不起作用,您仍然会遇到重新进入问题并收到InvalidOperationException“无法在 CollectionChanged 事件期间更改 ObservableCollection”的说法。

我必须使用 UI 的调度程序并禁用/启用事件处理程序以避免这些问题。

请注意:这是一个 hack,框架设计者竭尽全力阻止你这样做。因此,如果您想无视他们的警告,请注意不要击中自己的脚。

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

这将避免异常,避免递归调用处理程序,并正确更新 UI。

于 2015-05-11T19:44:12.480 回答