我正在按照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”错误。
我重新编译,导航到报告,它加载正常。我离开了,现在我得到一个弹出窗口,上面写着'对象引用没有设置为对象的实例。'我没问题,弹出窗口消失,我的程序继续没有任何明显的问题。我可以导航回报告没有任何问题,但每次我离开时都会显示此弹出窗口。
我无法调试弹出窗口的来源,因为如果我删除了所有者,它会被查看者无法找到所有者以显示错误而被吞没。
对于罗嗦的描述感到抱歉。该项目非常庞大,因此尝试使用源代码比使用它的描述需要更多的空间。如果您想查看我的代码的任何特定部分,只需发表评论,我就会更新我的问题。
答案 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;
}
}
}