主应用程序窗口,减去大量不相关的代码。
<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>
绑定(bind)到窗口的 View 模型
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
是具有许多依赖属性的用户控件,这些属性绑定(bind)到各自 View 模型中的属性。
// 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()
时,内容呈现器显示正确的用户控件并且所有属性都正确绑定(bind)。
在调用 ShowSecond()
时,内容呈现器显示正确的用户控件并且所有属性都正确绑定(bind)。
有时,在两个 View 之间切换时,我会在其中一个用户控件的依赖属性中遇到空引用异常,因为我的某些属性会查看其他依赖属性。这让我相信 View 模型在 View 之前被垃圾收集,并且 View 模型的更改触发了 usercontrols 依赖属性,这反过来又抛出异常,因为 View 模型不再存在。
我可以防止在处理 View 模型时触发依赖属性吗?
或者是否有必要在每个依赖属性中进行空数据上下文检查?
我应该在此处包含一些内容来查看用户控件的生命周期以完全防止这种情况发生吗?
最佳答案
WPF 在绑定(bind)时通常对其所有绑定(bind)操作使用弱引用,以防止发生内存泄漏。
因此,您的 ViewModel
可能会在某个时候被清理并消失,而控件仍然“活着”,因为 ViewModel 上的 GC 可能在 View 实际出现之前发生关掉了。
最简单的解决方案通常是使用空检查来处理这些更改通知,并跳过代码的适当部分。这也可能很有用,具体取决于您在初始化/创建时的设置方式。
关于c# - 具有依赖属性的 ContentPresenter 和 Datatemplates,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19792890/