Windows phone RxUI:从集合中删除项后出现异常

Windows phone RxUI:从集合中删除项后出现异常,windows-phone,reactiveui,Windows Phone,Reactiveui,我正在编写简单的WP7应用程序来研究ReactiveUI。 我想在屏幕上显示一个集合,项目应该是可选择的,我想有一个命令从集合中删除所有选定的项目。此外,该命令必须仅在至少有一个选定项时才可执行。 我用以下方式定义了一个集合: Persons = model.Persons .CreateDerivedCollection(x => new PersonViewModel(x)); 在PersonViewModel中,我有一个属性: private boo

我正在编写简单的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按钮处于活动状态。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)
at系统。线程。联锁。减量(Int64和位置)
在ReactiveUI.RefcountDisposeWrapper.Release()处
在ReactiveUI.ReactiveCollection`1.removeItemFromPropertyTracking(PersonViewModelToIntrack)
在ReactiveUI.ReactiveCollection`1.b___18(PersonViewModelx)
在System.Reactive.AnonymousObserver`1.Next(PersonViewModelvalue)中
at System.Reactive.AbstractObserver`1.OnNext(PersonViewModelvalue)
在System.Reactive.AutoDetachObserver`1.Next(PersonViewModelvalue)处
at System.Reactive.AbstractObserver`1.OnNext(PersonViewModelvalue)
在System.Reactive.ScheduledObserver`1.c_uudisplayClass4.b_uu2()
在System.Reactive.ScheduledObserver`1.b_u_0(操作本身)
at System.Reactive.Concurrency.Scheduler.b_uu0(操作'1'操作,操作'1自身)
在System.Responsive.Concurrency.Scheduler.c__DisplayClass9`1.b__6(操作`1状态1)
at System.Reactive.Concurrency.Scheduler.InvokeRec1[TState](ISScheduler调度器,对'2)
at System.Reactive.Concurrency.DispatcherScheduler.c_udisplayClass1`1.b_u0()
在System.Reflection.RuntimeMethodInfo.InternalInvoke(RuntimeMethodInfo rtmi、对象obj、BindingFlags invokeAttr、绑定器绑定器、对象参数、CultureInfo区域性、布尔值isBinderDefault、程序集调用者、布尔值验证访问、堆栈爬网标记和堆栈标记)
位于System.Reflection.RuntimeMethodInfo.InternalInvoke(对象obj、BindingFlags invokeAttr、绑定绑定器、对象[]参数、CultureInfo区域性、StackScrawMark和stackMark)
在System.Reflection.MethodBase.Invoke(对象obj,对象[]参数)处
位于System.Delegate.DynamicInvokeOne(对象[]args)
位于System.MulticastDelegate.DynamicInvokeImpl(对象[]args)
位于System.Delegate.DynamicInvoke(对象[]args)
在System.Windows.Threading.DispatcherOperation.Invoke()中
在System.Windows.Threading.Dispatcher.Dispatch中(DispatcherPriority优先级)
位于System.Windows.Threading.Dispatcher.OnInvoke(对象上下文)
位于System.Windows.Hosting.CallbackCookie.Invoke(对象[]args)
位于System.Windows.Hosting.DelegateWrapper.InternalInvoke(对象[]args)
位于System.Windows.RuntimeHost.ManagedHost.InvokeDelegate(IntPtr pHandle、Int32 nParamCount、ScriptParam[]pParams、ScriptParam&pResult)
我做错了,但有什么问题?我无法从ST.那里理解实施这种行为的正确方式。这很普遍,不是吗

upd


如果我删除所有关于deleteSelectedCanExecute的代码并运行程序,它就会崩溃。如果我删除
Participants.ChangeTrackingEnabled=true-它的工作原理与我预期的一样

安东,你是一个新版本的骄傲拥有者,你的崩溃应该消失

至于您关于选择的问题,如果集合可以更改大小,这是一个目前有点棘手的场景。某个地方的代码不仅必须订阅集合中的每个项目,还必须保留正在添加或删除的项目的列表(即有两种不再选择的方式,item.IsSelectedtrue=>false,或正在删除的项目

如果您没有快速变化的列表,您可以采用一种效率较低但简单得多的方法:

var cmd = new ReactiveCommand(
    Persons.ItemsCountChanged.Select(_ => 
        Persons.Any(x => x.IsSelected)));
顺便说一句,这个解决方案也不需要
changetrackingabled
,所以您不需要解决我刚刚修复的bug