Print a ListView control’s contents on multiple pages in C#


This example continues the following two examples:

Read those examples for an overview of the basic procedure. This example prints the contents of a ListView when the control contains too much information to print on a single page.

When a program prints in .NET, the PrintDocument object calls the PrintPage event handler to generate each page. That program should set the event handler’s e.HasMorePages parameter to indicate whether there are more pages to print.

This example keeps track of the next ListView row that needs to be printed. The PrintPage event handler starts printing at that row, updates the next row when it finishes printing the page, and sets e.HasMorePages appropriately.

The program’s changes are in the ListViewExtensions module, which adds extension methods to the ListView control. The module now includes the following variable to keep track of the next ListView row to print.

// The index of the next ListView row to be drawn.
private static int NextListViewRow = 0;

The pdocListView_PrintPage method, which is the PrintPage event handler used for printing, now passes the PrintMultiLineData method the bottom margin of the printed page so that method knows how much room it has for printing.

// Print the ListView.
e.HasMorePages = !lvwBooks.PrintMultiLineData(
    e.Graphics, Brushes.Blue,
    Brushes.Black, Pens.Blue);

The PrintMultiLineData method also now returns true if all of the data was printed. The PrintPage event handler uses the returned value to set e.HasMorePages.

The PrintMultiLineData method is similar to the previous version except it passes the bottom margin to the DrawMultiLineItems method that actually does the drawing.

if (!DrawMultiLineItems(subitems_query.ToArray(),
    gr, lvw.Font, data_brush, grid_pen,
    max_y, x_margin, y_margin,
    x, ref y, col_wids, num_columns, string_format)) return false;

The DrawMultiLineItems measures ListView row and, if it fits on the page, draws it and returns true. If the row doesn’t fit, then the method doesn’t draw the row and it returns false.

If the DrawMultiLineItems method returns false to indicate that the row didn’t fit, then the PrintMultiLineData method also returns false so the PrintPage event handler knows there are more rows to print.

If DrawMultiLineItems returns true, then PrintMultiLineData increments NextListViewRow so it can print the next row and continues.

The final change is to the DrawMultiLineItems method. Before printing the current row, the method now measures its fields to see how tall the row will be. If the new row will exceed the available height vertically, then the method returns false to indicate that it didn’t print the row. The following code shows this part of the method.

// Measure the size needed by the text.
for (int i = 0; i < num_columns; i++)
    SizeF layout_area = new SizeF(col_wids[i], 1000);
    SizeF row_size = gr.MeasureString(items[i], lvw_font,
    if (row_height < row_size.Height) row_height = row_size.Height;

// See if we have enough room for the row.
if (y0 + row_height > max_y) return false;

// Draw the text.

The rest of the method prints a row as before. See the previous examples for more details.

Note that this example doesn’t handle the case where a single row in the ListView is so tall that it can’t fit alone on a page. That should be a fairly unusual case, however.

Download Example   Follow me on Twitter   RSS feed   Donate

This entry was posted in controls, extension methods, printing and tagged , , , , , , , , , , , , , . Bookmark the permalink.

4 Responses to Print a ListView control’s contents on multiple pages in C#

  1. Anil Raina says:

    what are the changes I have to do with the ListViewExtension Class

  2. bright says:

    Can u help me with sample program that will read SMS received

Leave a Reply

Your email address will not be published. Required fields are marked *