我正在编写简单的 WP7 应用程序来研究 ReactiveUI。我想在屏幕上显示一个集合,项目应该是可选择的,并且我想要一个命令从集合中删除所有选定的项目。此外,该命令必须仅在至少有一个选定项目时才可执行。我有一个以这种方式定义的集合:
Persons = model.Persons
.CreateDerivedCollection(x => new PersonViewModel(x));
在PersonViewModel
我有一个属性:
private bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set { this.RaiseAndSetIfChanged(x => x.IsSelected, ref _isSelected, value); }
}
模型中没有关于选择状态的信息,只是在 viewModel 中。在 Page ViewModel 我有这个代码:
Persons = model.Persons.CreateDerivedCollection(x => new PersonViewModel(x));
Persons.ChangeTrackingEnabled = true;
var deleteSelectedCanExecute = Persons.ItemChanged
.Select(_ => Persons .Any(p => p.IsSelected));
DeleteSelectedCommand = new ReactiveCommand
(
deleteSelectedCanExecute
);
DeleteSelectedCommand.Subscribe(
x => RemoveSelected()
);
和一个方法:
private void RemoveSelected()
{
var res = Persons.Where(p => p.IsSelected)
.Select(x => x.Model).ToList();
foreach (var person in res)
{
_model.Persons.Remove(person);
}
}
第一个问题(不是那么重要,我想我可以自己找到解决方案):当我运行应用程序时,DeleteSelected 按钮是 Active.DeleteSelectedCommand.CanExecute 不会触发。但是,在选择/取消选择任何项目后 - 按钮状态工作正常。
和主要问题:
在我运行 DeleteSelectedCommand 后,它会删除所有选定的项目(我在调试器中看到它)。然后我得到了带有以下堆栈跟踪的“NotSupportedException”:
at System.Threading.Interlocked.Decrement(Int64& location)
at ReactiveUI.RefcountDisposeWrapper.Release()
at ReactiveUI.ReactiveCollection`1.removeItemFromPropertyTracking(PersonViewModel toUntrack)
at ReactiveUI.ReactiveCollection`1.<setupRx>b__18(PersonViewModelx)
at System.Reactive.AnonymousObserver`1.Next(PersonViewModelvalue)
at System.Reactive.AbstractObserver`1.OnNext(PersonViewModelvalue)
at System.Reactive.AutoDetachObserver`1.Next(PersonViewModelvalue)
at System.Reactive.AbstractObserver`1.OnNext(PersonViewModelvalue)
at System.Reactive.ScheduledObserver`1.<>c__DisplayClass4.<Next>b__2()
at System.Reactive.ScheduledObserver`1.<EnsureActive>b__0(Action self)
at System.Reactive.Concurrency.Scheduler.<Schedule>b__0(Action`1 _action, Action`1 self)
at System.Reactive.Concurrency.Scheduler.<>c__DisplayClass9`1.<InvokeRec1>b__6(Action`1 state1)
at System.Reactive.Concurrency.Scheduler.InvokeRec1[TState](IScheduler scheduler, Pair`2 pair)
at System.Reactive.Concurrency.DispatcherScheduler.<>c__DisplayClass1`1.<Schedule>b__0()
at System.Reflection.RuntimeMethodInfo.InternalInvoke(RuntimeMethodInfo rtmi, Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess, StackCrawlMark& stackMark)
at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, StackCrawlMark& stackMark)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at System.Delegate.DynamicInvokeOne(Object[] args)
at System.MulticastDelegate.DynamicInvokeImpl(Object[] args)
at System.Delegate.DynamicInvoke(Object[] args)
at System.Windows.Threading.DispatcherOperation.Invoke()
at System.Windows.Threading.Dispatcher.Dispatch(DispatcherPriority priority)
at System.Windows.Threading.Dispatcher.OnInvoke(Object context)
at System.Windows.Hosting.CallbackCookie.Invoke(Object[] args)
at System.Windows.Hosting.DelegateWrapper.InternalInvoke(Object[] args)
at System.Windows.RuntimeHost.ManagedHost.InvokeDelegate(IntPtr pHandle, Int32 nParamCount, ScriptParam[] pParams, ScriptParam& pResult)
所以我做错了,但问题是什么?我无法从 ST 中理解。实现此行为的正确方法是什么。这很常见不是吗?
更新
如果我删除有关 deleteSelectedCanExecute 的所有代码并运行程序 - 它会崩溃。如果我删除Participants.ChangeTrackingEnabled = true;
- 它会按我的预期工作。