在ViewModelViewHost控件

时间:2016-04-05 17:59:55

标签: c# .net wpf reactiveui

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

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

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

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来隐藏视图。

我做错了吗?

修改:这里是完整的源代码:https://gist.github.com/dmakaroff/e7d84e06e0a48d7f5298eb6b7d6187d0

按第一个Show然后按Hide按钮将产生以下输出:

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

2 个答案:

答案 0 :(得分:9)

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

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

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

原因在于,由于您的视图正在销毁/处置,因此激活订阅本身也需要作为此过程的一部分进行处理。

答案 1 :(得分:0)

您可以查看this link。所有事情都有很好的表达。在我不知道你在“视图”中做了什么的情况下,我就可以提供这一切。

“ViewModel和View”可能会被调用两次,因为您正在创建两个LoadingViewModel。