打印图表控件时,PrintPage事件保持无限循环

时间:2016-11-13 14:08:03

标签: c# winforms printing charts

我发现了一些问题,但没有什么可以帮助我的逻辑。我有以下代码(显示不是全部因为它太多了):

 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);
    }

现在我想做什么: 我遍历DataTable。每隔几行我创建一个新的ChartArea,将这些行中的一些值绑定到Series并将其绑定到ChartArea。我实际上正在将ChartAreas绘制到我的Chart Control中。每两个ChartAreas我打印控件,清理它,并绘制下两个ChartAreas(最后有12个 - 所以6次绘制到图表控件)。这有效,但我希望实现以下目标: 我想为每个图表控件添加一个新页面到我的打印事件,这样我最后有6页,然后将其打印到一个文件(pdf)。不知何故,由于e.HasMorePages属性,它会进入printPage事件的不定式循环。这如何与图表一起使用? 非常感谢你!

1 个答案:

答案 0 :(得分:1)

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

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

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

// 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));
    }
}

当我使用预览控件运行时,这就是我得到的:

enter image description here