【问题标题】:PrintPage Event stays in endless loop while printing Chart ControlPrintPage 事件在打印图表控件时保持无限循环
【发布时间】:2016-11-13 14:08:02
【问题描述】:

我在这方面发现了一些问题,但对我的逻辑没有任何帮助。我有以下代码(不显示全部,因为它太多了):

 public int AreaCounter { get; set; } = 0;
 public PrintDocument pd { get; set; }

 public void PrintCharts(DataTable dt)
 {
        foreach (DataRow row in dt.Rows)
        {
           //after a couple of rows - here is code for creating
           //a new chartArea and binding the points to the series
           //plus binding that series to the area

           if(// two chartAreas have been created with each one having a chart)
             {
               PrintChartControl();
             }
             AreaCounter++;
        }
 }

  private void PrintChartControl()
  {
    pd.PrintPage += pd_PrintPage;
    pd.Print();
  }

    private void pd_PrintPage(object sender, PrintPageEventArgs e)
    {
        if (AreaCounter < 11) //12 ChartAreas have to be created
            e.HasMorePages = true;
        else
            e.HasMorePages = false;

        var myRec = e.MarginBounds;
        Container.chart1.Printing.PrintPaint(e.Graphics, myRec);
    }

现在我想做的是: 我循环通过一个数据表。每隔几行,我就会创建一个新的 ChartArea,将这些行中的一些值绑定到一个系列,并将其绑定到 ChartArea。我实际上是在将 ChartAreas 绘制到我的图表控件中。每两个 ChartAreas 我打印控件,清理它,然后绘制接下来的两个 ChartAreas(最后有 12 个 - 所以 6 次绘制到图表控件)。这可行,但我想实现以下目标: 我想为我的打印事件中的每个图表控件添加一个新页面,以便最后有 6 页,然后将其打印到一个文件(pdf)中。由于 e.HasMorePages 属性,它以某种方式进入 printPage 事件中的不定式循环。这如何与图表一起使用? 非常感谢!

【问题讨论】:

  • 你在哪里增加AreaCounter
  • 抱歉忘记了。编辑代码
  • 您必须将您的打印逻辑和循环控制带到 PrintPage 事件处理程序中。看看this answer of mine 是否有帮助。
  • 我不完全知道如何在我的情况下使用它。 IEnumerator> ObjectsEnumerator;做我的 AreaCounter?
  • 不,应该是你的 dt.Rows

标签: c# winforms printing charts


【解决方案1】:

您最好让PrintDocument 类驱动您的数据,而不是您尝试驱动PrintDocument。 PrintDocument 类将引发PrintPage 事件,我们的任务是为该单页提供数据。数据进入PrintPageEventArgs 中提供的Graphics 实例。如果我们想打印另一页,我们确保HasMorePages 为真,printdocument 实例将再次调用PrintPage,我们为下一页提供数据等。当我们没有更多数据并且不想要更多页面时被打印,我们将HasMorePages设置为false。

根据您的代码,我创建了以下示例,希望适用于您的案例。

我假设 DataTable 中的行是确定是否需要打印以及需要打印多少页的主要来源。如果不是基于此,您可以为不同的集合/数组创建一个 Enumerator,机制保持不变。

// the reference to the enumerator for the DataRows
IEnumerator rows;

private void printDocument1_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
{
    var dataTable = Load();
    rows = dataTable.Rows.GetEnumerator();
}

private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
    // no rows, no glory
    if (rows == null) return;

    // keep track of stuff
    var chartsOnthisPage = 0;
    var yPos = 20f;

    // loop for what needs to go on this page, atm it prints 2 charts
    // as long as there are rows
    // the enumerator is moved to the next record ...
    while ((e.HasMorePages = rows.MoveNext()))
    {
        // ... get hold of that datarow 
        var currentRow = (DataRow)rows.Current;

        // print
        e.Graphics.DrawString(currentRow[0].ToString(), Font, Brushes.Black, 0, yPos);
        // keep track where we are
        yPos = yPos + 40;

        // do what ever is need to print the chart fro this row
        GenerateChart(currentRow);
        // print the chart
        chart1.Printing.PrintPaint(e.Graphics, new Rectangle(0, (int)yPos, 200, 200));
        // position tracking
        yPos = yPos + 200;
        // optionaly break here if we reached the end of the page
        // keep track 
        chartsOnthisPage++;
        if (chartsOnthisPage > 1) break; // HasMorePages is set
    }
}

private void printDocument1_EndPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
{
   // clean up;
    rows = null;  
}

我有两种辅助方法,一种用于创建包含行的 DataTable,另一种用于生成一些有趣的图表。

private DataTable Load()
{
    var dt = new DataTable();
    dt.Columns.Add("chart");

    for(int r=0; r<10; r++)
    {
        var rw = dt.NewRow();
        rw[0] = Guid.NewGuid().ToString("N");
        dt.Rows.Add(rw);
    }
    return dt;
}

Random rnd = new Random();
private void GenerateChart(DataRow row)
{
    chart1.Series.Clear();
    chart1.Series.Add("data");
    var mx = rnd.Next(rnd.Next(10) + 3);
    for (int x = 0; x < mx; x++)
    {
        chart1.Series[0].Points.Add(x, rnd.Next(100));
    }
}

当我使用预览控件运行它时,我得到了:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-07
    • 2017-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-24
    相关资源
    最近更新 更多