2

嗨,伙计们,我一直在使用 WPF C# 工作和搜索报告,并找到了一份不错的报告,而且也很容易,找到了这个链接并使用它。所以我尝试使用它,请检查我的代码,

在我EmployeeProfileWindow的打印按钮中,

private void btnprintviolation_Click(object sender, RoutedEventArgs e)
{
    ReportViolationWindow NewReportViolationWindow = new ReportViolationWindow();
    //Windows.Add(NewReportViolationWindow);
    GlobalVar.ViolationEmpNum = txtdispid.Text;
    GlobalVar.ViolationRefNumToPrint.Clear();
    for (int i = 0; i < lvviolations.Items.Count; i++)
    {
        GlobalVar.ViolationRefNumToPrint.Add(((EmpViolationObject)lvviolations.Items[i]).VioRefNum);
    }
    NewReportViolationWindow.Show();
}

因此,如果我单击该按钮,它将出现一个新的窗口名称NewReportViolationWindow。我将在模板文件夹中复制或编辑开源示例中的内容。我创建了名为 的报告ReportViolation

现在这里是后面的代码NewReportViolationWindow

ReportDocument reportDocument = new ReportDocument();
string ats = new DirectoryInfo(Environment.CurrentDirectory).Parent.Parent.FullName;
StreamReader reader = new StreamReader(new FileStream(ats.ToString() + @"\Template\ReportViolation.xaml", FileMode.Open, FileAccess.Read));
reportDocument.XamlData = reader.ReadToEnd();
reportDocument.XamlImagePath = Path.Combine(ats.ToString(), @"Template\");
reader.Close();


DateTime dateTimeStart = DateTime.Now; // start time measure here
List<ReportData> listData = new List<ReportData>();
//foreach (string item in GlobalVar.ViolationRefNumToPrint)
for (int i = 0; i < 5 ; i++)
{
    ReportData data = new ReportData();

    data.ReportDocumentValues.Add("PrintDate", DateTime.Now);
    data.ReportDocumentValues.Add("EmpIDNum", NewIDNumber.ToString());
    data.ReportDocumentValues.Add("EmpName", NewEmpName.ToString());
    data.ReportDocumentValues.Add("EmpPosition", NewPosition.ToString());

    //data.ReportDocumentValues.Add("VioRefCode", item.ToString());
    listData.Add(data);
}

XpsDocument xps = reportDocument.CreateXpsDocument(listData);
documentViewer.Document = xps.GetFixedDocumentSequence();

// show the elapsed time in window title
Title += " - generated in " + (DateTime.Now - dateTimeStart).TotalMilliseconds + "ms";

}
catch (Exception ex)
{
    // show exception
    MessageBox.Show(ex.Message + "\r\n\r\n" + ex.GetType() + "\r\n" + ex.StackTrace, ex.GetType().ToString(), MessageBoxButton.OK, MessageBoxImage.Stop);
}

现在,当我运行我的应用程序并单击打印按钮时。有时一开始它会毫无错误地打开,NewReportViolationWindow但是当我尝试关闭报告或再次单击按钮时,它会给出一条消息,

指定的 Visual 已经是另一个 Visual 的子对象或组件目标的根

这是错误的图像,

在此处输入图像描述

我认为问题是当我调用打印按钮后面的代码的打印报告时,任何人都可以吗?请... :)

第二次编辑

关于你的问题:

  • 您说报告窗口通常第一次打开时没有错误,但之后就没有了?

是,对的..

  • 中是否有任何共享资源正在使用 ReportViolationWindow

抱歉,我不知道我所做的只是遵循开源中的示例。

  • 你是如何处理/处理关闭的 ReportViolationWindow

到目前为止,我仍然没有正确关闭我的ReportViolationWindow. 当我单击关闭按钮时,就是这样,对不起。:(

  • 您是否保留对此ReportViolationWindow 实例的任何其他引用?

没有。据我所知。

4

2 回答 2

1

您必须先将 Visual 从其当前父级“分离”,然后才能将其添加到新父级 - 原因主要是由于渲染和合成引擎的工作方式;如果原始父元素不知道它不再负责渲染该子元素,并且 WPF 允许您将其附加到另一个父元素,则在最好的情况下,您将渲染重复的视觉对象,而在最坏的情况下在这种情况下,您可能会陷入无限循环!

由于添加/删除子元素的责任在于父元素,因此您需要在父元素级别处理此问题,通常通过调用RemoveLogicalChildRemoveVisualChild(或者理想情况下,从原始 ItemsSource 中删除项目本身并将其添加到新的一)

编辑:从技术上讲,第一段是正确的,但我认为第二段不适用于您......在查看CodePlex 上的 WpfReportsReportPaginator类的源代码后,我注意到以下内容:

  • 我相信最新版本与您的不同:# 行不太匹配。可能这是一个已修复的错误?
  • (挑剔)我不喜欢这段代码的结构(即报告引擎)......ArrayLists?单行 if/else/return 语句?

现在,对于您的实际问题:

  • 您说报告窗口通常第一次打开时没有错误,但之后就没有了?

  • 中是否有任何共享资源正在使用ReportViolationWindow

  • 你是如何处理/处理关闭的ReportViolationWindow

  • 您是否保留对此实例的任何其他引用?ReportViolationWindow

为了查看错误是否继续,我会尝试的一件事是NewReportViolationWindow在创建它的窗口中声明一个类型的单个成员变量(EmployeeProfileWindow),而不是这个:

private void btnprintviolation_Click(object sender, RoutedEventArgs e)
{
    ReportViolationWindow NewReportViolationWindow = new ReportViolationWindow();

尝试类似:

ReportViolationWindow _reportViolationWindow;
private void btnprintviolation_Click(object sender, RoutedEventArgs e)
{
    if(_reportViolationWindow != null)
    {
        _reportViolationWindow.Close();
        _reportViolationWindow = null;
    }
    _reportViolationWindow = new ReportViolationWindow();
于 2012-11-17T02:06:25.057 回答
1

好的,我可能有一个解决方案。如果我将上面的第二个代码片段更改为

代码块

ContainerVisual smallerPage = new ContainerVisual( );

DrawingVisual pageVisual = page.Visual as DrawingVisual;

if ( pageVisual != null && pageVisual.Parent != null )

{

ContainerVisual parent = pageVisual.Parent as ContainerVisual;

parent.Children.Remove( pageVisual );

}

smallerPage.Children.Add( page.Visual );

它似乎工作。请评论。我很想知道是否有更好的方法。这似乎是一个黑客。

于 2015-03-03T08:01:54.560 回答