主应用程序窗口,减去大量不相关的代码。
<Window>
<Window.Resources>
<DataTemplate DataType="{x:Type presenters:DashboardViewModel}">
<views:DashboardView />
</DataTemplate>
<DataTemplate DataType="{x:Type presenters:SecondViewModel}">
<views:SecondView />
</DataTemplate>
</Window.Resources>
<ContentPresenter Content="{Binding WindowPresenter}"/>
</Window>
绑定到Window
的视图模型public class RootViewModel {
// IRL this implements notifypropchanged
public IPresenter WindowPresenter {get; set;}
public void ShowDashboard(){ this.WindowPresenter = new DashBoardViewModel(); }
public void ShowSecond(){ this.WindowPresenter = new SecondViewModel(); }
}
DashboardView
和SecondView
是具有许多依赖项属性的用户控件,这些属性绑定到其各个视图模型中的属性。
// example of a common dependency property I have
public static readonly DependencyProperty ColorPaletteProperty = DependencyProperty.Register("ColorPalette", typeof(ColorPalette), typeof(SurfaceMapControl), new PropertyMetadata(ColorPalette.Rainbow, new PropertyChangedCallback(SurfaceMapControl.ColorPalettePropertyChanged)));
private static void ColorPalettePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((SurfaceMapControl)d).OnColorRangeChanged(); }
private void OnColorRangeChanged() {
// code that uses this.SomeOtherDependencyProperty
// throws null ref exception
}
调用ShowDashboard()
时,内容呈现器会显示正确的用户控件,并且所有属性都会正确绑定。
在调用ShowSecond()
时,内容呈现器显示正确的用户控件,并且所有属性都正确绑定。
偶尔在两个视图之间切换时,我会在其中一个用户控件的依赖项属性中获得null ref异常,因为我的一些属性会查看其他依赖项属性。这使我相信viewmodel在视图之前被垃圾收集,并且viewmodel中的更改会触发usercontrols依赖项属性,从而抛出异常,因为viewmodel不再存在。
我可以阻止在配置视图模型时触发依赖项属性吗?
或者是否有必要在每个依赖项属性中进行null datacontext检查?
我是否应该在此处查看用户控件的生命周期以防止这种情况发生?
答案 0 :(得分:1)
WPF,绑定时,通常对所有绑定操作使用弱引用,以防止发生内存泄漏。
因此,您的ViewModel
可能会被清理并在某个时刻消失,而控件仍处于“活动状态”,因为ViewModel上的GC可能会在视图实际切换之前发生。
最简单的解决方案通常是使用空检查来处理这些更改通知,并跳过代码的相应部分。根据您在初始化/创建时的设置方式,这也很有用。