ReactiveUI OneWayBind 泄漏句柄
ReactiveUI OneWayBind leaks handles
我有一个简单的 ViewModel:
public class MeetingPageViewModel : ReactiveObject, IRoutableViewModel
{
public MeetingPageViewModel(IScreen hs, IMeetingRef mRef)
{
HostScreen = hs;
_backing = "hi there";
}
public IScreen HostScreen { get; private set; }
public string MeetingTitle
{
get { return _backing; }
set { this.RaiseAndSetIfChanged(ref _backing, value); }
}
string _backing;
public string UrlPathSegment
{
get { return "/meeting"; }
}
}
然后我将 MeetingTitle 绑定到一个 TextBlock:
public sealed partial class MeetingPage : Page, IViewFor<MeetingPageViewModel>
{
public MeetingPage()
{
this.InitializeComponent();
// Bind everything together we need.
this.OneWayBind(ViewModel, x => x.MeetingTitle, y => y.MeetingTitle.Text);
}
/// <summary>
/// Stash the view model
/// </summary>
public MeetingPageViewModel ViewModel
{
get { return (MeetingPageViewModel)GetValue(ViewModelProperty); }
set { SetValue(ViewModelProperty, value); }
}
public static readonly DependencyProperty ViewModelProperty =
DependencyProperty.Register("ViewModel", typeof(MeetingPageViewModel), typeof(MeetingPage), new PropertyMetadata(null));
object IViewFor.ViewModel
{
get { return ViewModel; }
set { ViewModel = (MeetingPageViewModel)value; }
}
}
导航回上一屏幕后,MeetingPageViewModel 未被垃圾回收。我正在使用 RxUI 6.4.1 和 VS2013(以及内存分析分析工具)。如果我处理 OneWayBind 中的 return 值,那么所有内容都会正确清理 - 但当然,我不再有绑定。
原来是 DependencyProperty ViewModel 的问题。它的生命周期是永远的(请注意其声明中的 "static" )。因此,附加到它的绑定永远不会被垃圾收集,因为它永远不会消失,然后该绑定会同时持有对视图和视图模型的引用,因此它们永远不会消失。
打破这一点的唯一方法是明确清理绑定。 RxUI 提供了 WhenActivated 方法来帮助解决这个问题。在 lambda 中包围绑定,并使用提供的函数来跟踪 IDisposals。当视图消失时,这将被清理。
this.WhenActivated(disposeOfMe => {
disposeOfMe (this.OneWayBind(ViewModel, x => x.MeetingTitle, y => y.MeetingTitle.Text));
});
我有一个简单的 ViewModel:
public class MeetingPageViewModel : ReactiveObject, IRoutableViewModel
{
public MeetingPageViewModel(IScreen hs, IMeetingRef mRef)
{
HostScreen = hs;
_backing = "hi there";
}
public IScreen HostScreen { get; private set; }
public string MeetingTitle
{
get { return _backing; }
set { this.RaiseAndSetIfChanged(ref _backing, value); }
}
string _backing;
public string UrlPathSegment
{
get { return "/meeting"; }
}
}
然后我将 MeetingTitle 绑定到一个 TextBlock:
public sealed partial class MeetingPage : Page, IViewFor<MeetingPageViewModel>
{
public MeetingPage()
{
this.InitializeComponent();
// Bind everything together we need.
this.OneWayBind(ViewModel, x => x.MeetingTitle, y => y.MeetingTitle.Text);
}
/// <summary>
/// Stash the view model
/// </summary>
public MeetingPageViewModel ViewModel
{
get { return (MeetingPageViewModel)GetValue(ViewModelProperty); }
set { SetValue(ViewModelProperty, value); }
}
public static readonly DependencyProperty ViewModelProperty =
DependencyProperty.Register("ViewModel", typeof(MeetingPageViewModel), typeof(MeetingPage), new PropertyMetadata(null));
object IViewFor.ViewModel
{
get { return ViewModel; }
set { ViewModel = (MeetingPageViewModel)value; }
}
}
导航回上一屏幕后,MeetingPageViewModel 未被垃圾回收。我正在使用 RxUI 6.4.1 和 VS2013(以及内存分析分析工具)。如果我处理 OneWayBind 中的 return 值,那么所有内容都会正确清理 - 但当然,我不再有绑定。
原来是 DependencyProperty ViewModel 的问题。它的生命周期是永远的(请注意其声明中的 "static" )。因此,附加到它的绑定永远不会被垃圾收集,因为它永远不会消失,然后该绑定会同时持有对视图和视图模型的引用,因此它们永远不会消失。
打破这一点的唯一方法是明确清理绑定。 RxUI 提供了 WhenActivated 方法来帮助解决这个问题。在 lambda 中包围绑定,并使用提供的函数来跟踪 IDisposals。当视图消失时,这将被清理。
this.WhenActivated(disposeOfMe => {
disposeOfMe (this.OneWayBind(ViewModel, x => x.MeetingTitle, y => y.MeetingTitle.Text));
});