ContentPresenter和带有依赖属性的Datatemplates

3
主要应用程序窗口,减去大量不相关的代码。
<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>

绑定到窗口的视图模型
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(); }
}

DashboardViewSecondView是用户控件,具有许多依赖属性,这些属性绑定到它们各自的视图模型中的属性。

// 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()时,内容呈现器会显示正确的用户控件,并且所有属性都正确绑定。
有时,在两个视图之间切换时,我会在一个用户控件的依赖属性上得到空引用异常,因为我的一些属性查看其他依赖属性。这让我相信,当视图模型被垃圾回收而视图未被垃圾回收时,视图模型的更改会触发用户控件的依赖属性,从而导致异常,因为视图模型不再存在。
我能否防止在视图模型被处理后触发依赖属性?
或者是否有必要在每个依赖属性中包含空数据上下文检查?
在这里是否需要包含某些内容来查看用户控件的生命周期以彻底解决这个问题?

空引用出现在哪里?DP的属性更改事件? - Rohit Vats
如上代码所述,this.SomeOtherDependencyProperty 为空。 - Charlie Brown
1个回答

1

当进行绑定时,WPF通常使用弱引用来防止内存泄漏。

因此,你的ViewModel可能在某个时刻被清除并消失,而控件仍然“存在”,因为在实际切换视图之前,ViewModel上的GC可能已经发生。

最简单的解决方案通常是通过空值检查处理这些更改通知,并跳过代码的相应部分。根据你如何设置事情,这也可以在初始化/创建时非常有用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接