大家好,我一直在努力寻找使用WPF C#的报告,并找到一个很好的报告,也很容易找到这个link并使用它。所以我试着用它,请检查我的代码,
在我的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
的任何其他引用
实例没有。据我所知。
答案 0 :(得分:1)
您必须先将Visual从其当前Parent中“分离”,然后才能将其添加到新Parent中 - 原因主要在于渲染和合成引擎的工作方式;如果原始父元素不知道它不再负责渲染该子节点,并且WPF允许您将其附加到另一个父节点,在最好的情况下,您将有重复的Visuals渲染,并且在最坏的情况下情景,你可能会陷入无限循环!
由于责任在Parent元素上添加/删除子元素,因此您需要在父级别处理此问题,通常需要调用 RemoveLogicalChild
或RemoveVisualChild
(或理想情况下,从原始ItemsSource中删除项目本身并将其添加到新项目
ReportPaginator
课程的源代码后,我注意到了以下内容:
现在,针对您的实际问题:
你说报告窗口通常是第一次打开而没有错误,但之后没有错误?
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();
答案 1 :(得分: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 );
似乎有效。请评论。我很想知道是否有更好的方法。这看起来像个黑客。