如何修复“对象引用未设置为对象的实例”。使用WPF CR Viewer Control时

时间:2013-01-03 16:36:50

标签: c# wpf crystal-reports

我正在按照MVVM模式制作WPF应用程序。

我有一个带导航控件的窗口以及一个占位符(contentcontrol)来保存单个用户控件。主窗口的viewmodel维护一个打开的子视图模型数组,并具有一个'CurrentView'属性,该属性指向数组中的单个子视图模型。然后将此“CurrentView”属性绑定到主窗口上的contentcontrol占位符。视图模型都通过数据模板设置了特定视图(用户控件)。

当'CurrentView'属性设置为其中一个子视图模型时,相应的用户控件视图将显示在主窗口的contentcontrol占位符中。一次只显示一个子视图模型,其余只是坐在数组中,等待通过设置为CurrentView属性来显示。

直到现在,我对这种模式没有任何问题。它适用于所有标准WPF控件,没有任何问题。我的问题是仅当我的一个用户控件托管WPF Crystal Report Viewer时。

我可以将当​​前视图设置为具有水晶报表reportdocument的viewmodel。我加载报表文档并将其公开为公共依赖项属性。此视图模型的数据模板化用户控件具有WPF Crystal Report Viewer控件。我在报表查看器控件中添加了一个附加属性,以允许我绑定到.ViewerCore.ReportSource。我将报表文档从viewmodel绑定到附加属性,瞧!所有这些都按预期工作。我编译我的程序并导航到水晶报表查看器...它加载绑定的报表并正确显示它。

然而,现在,当我离开时(用不同的视图模型替换主窗口上的'CurrentView'属性),我收到错误。

起初,我得到了“未设置属性:窗口”。经过一番搜索后,我发现Crystal Report Viewer正试图显示一个消息框,但是却没有知道它的所有者窗口,所以它不能。为了解决这个问题,我将水晶报表查看器的所有者设置为用户控件加载事件中的主窗口。这摆脱了“Property not set:Window”错误。

我重新编译,导航到报告,它加载正常。我离开了,现在我得到一个弹出窗口,上面写着'对象引用没有设置为对象的实例。'我没问题,弹出窗口消失,我的程序继续没有任何明显的问题。我可以导航回报告没有任何问题,但每次我离开时都会显示此弹出窗口。

我无法调试弹出窗口的来源,因为如果我删除了所有者,它会被查看者无法找到所有者以显示错误而被吞没。

对于罗嗦的描述感到抱歉。该项目非常庞大,因此尝试使用源代码比使用它的描述需要更多的空间。如果您想查看我的代码的任何特定部分,只需发表评论,我就会更新我的问题。

1 个答案:

答案 0 :(得分:1)

我尝试了一堆不同的断点,并且能够将其缩小到我附加的依赖属性以绑定到ViewerCore.ReportSource。当我改变到不同的视图时,此属性意外地设置为null,并且附加的属性没有考虑到这一点。如果将来有人遇到类似问题,您可以使用以下内容:

public static class DependencyPropertyHost
{
    public static readonly DependencyProperty ReportSourceProperty = DependencyProperty.RegisterAttached("ReportSource", typeof(ReportDocument), typeof(DependencyPropertyHost), new PropertyMetadata(ReportSourceChanged));

    public static ReportDocument GetReportSource(DependencyObject obj)
    {
        return obj.GetValue(ReportSourceProperty) as ReportDocument;
    }

    public static void SetReportSource(DependencyObject obj, ReportDocument value)
    {
        obj.SetValue(ReportSourceProperty, value);
    }

    private static void ReportSourceChanged(object sender, DependencyPropertyChangedEventArgs args)
    {
        var viewer = sender as CrystalReportsViewer;
        if (viewer != null && args.NewValue != null)
        {
            viewer.ViewerCore.ReportSource = args.NewValue;
        }
    }
}