WhenActivated 在 ViewModelViewHost 控件中托管的 Views 和 ViewModel 中使用时被调用两次
WhenActivated is called twice when used in Views and ViewModels hosted in ViewModelViewHost control
我的应用程序使用实现 IViewFor<T>
接口的视图。这些视图在 AppBootstrapper
中注册到依赖项解析器。该应用通过将相应的视图模型分配给控件的 ViewModel
属性,使用 ViewModelViewHost
控件显示视图。所有视图模型都实现了 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 属性 设置为空来隐藏视图。
我是不是做错了什么?
编辑: 这是完整的源代码:https://gist.github.com/dmakaroff/e7d84e06e0a48d7f5298eb6b7d6187d0
先按显示然后按隐藏按钮会产生以下输出:
SubViewModel activated.
SubView activated.
SubViewModel deactivated.
SubView deactivated.
SubViewModel activated.
SubView activated.
SubViewModel deactivated.
SubView deactivated.
您可以查看this link。一切都有很好的解释。这就是我在不了解您在“视图”中所做的事情的情况下所能提供的全部内容。
“ViewModel 和 View”可能被调用了两次,因为您正在创建两个 LoadingViewModel。
WhenActivated
调用在 SubView
returns 一个 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
});
此解决方案之所以有效,是因为您的视图正在被销毁,激活本身也需要作为此过程的一部分进行处理。
我的应用程序使用实现 IViewFor<T>
接口的视图。这些视图在 AppBootstrapper
中注册到依赖项解析器。该应用通过将相应的视图模型分配给控件的 ViewModel
属性,使用 ViewModelViewHost
控件显示视图。所有视图模型都实现了 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 属性 设置为空来隐藏视图。
我是不是做错了什么?
编辑: 这是完整的源代码:https://gist.github.com/dmakaroff/e7d84e06e0a48d7f5298eb6b7d6187d0
先按显示然后按隐藏按钮会产生以下输出:
SubViewModel activated.
SubView activated.
SubViewModel deactivated.
SubView deactivated.
SubViewModel activated.
SubView activated.
SubViewModel deactivated.
SubView deactivated.
您可以查看this link。一切都有很好的解释。这就是我在不了解您在“视图”中所做的事情的情况下所能提供的全部内容。
“ViewModel 和 View”可能被调用了两次,因为您正在创建两个 LoadingViewModel。
WhenActivated
调用在 SubView
returns 一个 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
});
此解决方案之所以有效,是因为您的视图正在被销毁,激活本身也需要作为此过程的一部分进行处理。