当在ViewModelViewHost控件中托管的Views和ViewModels中使用时,WhenActivated被调用两次. [英] WhenActivated is called twice when used in Views and ViewModels hosted in ViewModelViewHost control

查看:48
本文介绍了当在ViewModelViewHost控件中托管的Views和ViewModels中使用时,WhenActivated被调用两次.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序使用视图,这些视图实现了 IViewFor< T> 界面.这些视图已在 AppBootstrapper 中的依赖项解析器中注册.该应用程序通过将相应的视图模型分配给控件的 ViewModel 属性来使用 ViewModelViewHost 控件显示视图.所有视图模型都实现 ISupportsActivation 接口.

My app uses views, which implement IViewFor<T> interface. The views are registered with the dependency resolver in AppBootstrapper. The app displays the views using ViewModelViewHost control by assigning a corresponding view model to control's ViewModel property. All the view models implement ISupportsActivation interface.

我注意到 WhenActivated 被调用了两次.首先,它在激活视图模型时被调用.然后在停用时处置所有一次性用品,并立即再次调用 WhenActivated ,然后处置一次性用品.

I noticed that WhenActivated is called twice. First it's called when a view and view model get activated. Then on deactivation all disposables are disposed and WhenActivated is called again immediately followed by disposing the disposables.

我正在视图和视图模型中使用以下代码进行测试:

I am testing with the following code both in view and view model:

this.WhenActivated(disposables =>
{
    Debug.WriteLine("ViewModel activated.");

    Disposable
        .Create(() =>
        {
            Debug.WriteLine("ViewModel deactivated.");
        })
        .AddTo(disposables);
});

结果输出如下:

// App displays the view:

ViewModel activated.
View activated.

// App hides the view:

ViewModel deactivated.
View deactivated.
ViewModel activated.
View activated.
ViewModel deactivated.
View deactivated.

通过将ViewModelViewHost控件的ViewModel属性设置为null可以隐藏视图.

The view is hidden by setting ViewModel property of ViewModelViewHost control to null.

我做错什么了吗?

,以下是完整的源代码: https://gist.github.com/dmakaroff/e7d84e06e0a48d7f5298eb6b7d6187d0

here's the complete source code: https://gist.github.com/dmakaroff/e7d84e06e0a48d7f5298eb6b7d6187d0

先按显示",然后按隐藏"按钮,将产生以下输出:

Pressing first Show and then Hide buttons produces the following output:

SubViewModel activated.
SubView activated.
SubViewModel deactivated.
SubView deactivated.
SubViewModel activated.
SubView activated.
SubViewModel deactivated.
SubView deactivated.

推荐答案

SubView 中使用的 WhenActivated 调用返回一个 IDisposable 对象,该对象可以在对 WhenActivated的同一调用中使用.会在停用后将您的订阅从激活事件中删除.这样做可以防止发生二次激活和处置.

The WhenActivated call used in SubView returns an IDisposable object, which can be used within the same call to WhenActivated. This will remove your subscription from activation events upon deactivation. Doing so prevents the secondary activation and disposal from occurring.

SubView 构造函数中,更改以下内容:

In the SubView constructor, change this:

this.WhenActivated(d =>
{
    Debug.WriteLine("SubView activated.");
    d(Disposable.Create(() => { Debug.WriteLine("SubView deactivated."); }));

    d(this // ViewModel -> DataContext
        .WhenAnyValue(v => v.ViewModel)
        .BindTo(this, v => v.DataContext));
});

对此:

System.IDisposable whenActivatedSubscription = null;
whenActivatedSubscription = this.WhenActivated(d =>
{
    Debug.WriteLine("SubView activated.");
    d(Disposable.Create(() => { Debug.WriteLine("SubView deactivated."); }));

    d(this // ViewModel -> DataContext
        .WhenAnyValue(v => v.ViewModel)
        .BindTo(this, v => v.DataContext));
    d(whenActivatedSubscription); // <- Dispose of the activation subscription here
});

此解决方案有效的原因是,由于您的视图已被破坏,因此激活本身也需要作为此过程的一部分进行处理.

The reason why this solution works is because since your view is being destroyed, the activation itself needs to be disposed of as a part of this process as well.

这篇关于当在ViewModelViewHost控件中托管的Views和ViewModels中使用时,WhenActivated被调用两次.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆