我有 2 个列表视图...并在它们之间添加/删除按钮。
在视图模型中列表视图集合的集合更改事件中,我可以回滚特定条件的更改吗?
您可以处理备份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;
}
}
}
考虑到您将事件的发送者作为一个对象(即事件的第一个参数)和已修改的对象列表,是的,您可以这样做。不过我不建议这样做。如果遇到这种情况,请在 ViewModel 上提供一个方法,该方法与 一起提供EventArgs
,并让它完成工作。视图不是做逻辑的地方。
更好的是:检查 ViewModel 本身的条件(即在可响应添加/删除的命令中)!视图模型对信息的状态是可响应的,因此请保留您的逻辑。视图只是用于显示数据。
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。