Print the contents of a ListView control with data that doesn't fit in one line or one one page 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 ListView 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.MarginBounds.Location,
    e.MarginBounds.Bottom,
    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;
NextListViewRow++;

The DrawMultiLineItems method draws a ListView row and returns true if the row fits. 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, layout_area);
    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.

   

 

What did you think of this article?




Trackbacks
  • No trackbacks exist for this post.
Comments
  • No comments exist for this post.
Leave a comment

Submitted comments are subject to moderation before being displayed.

 Name

 Email (will not be published)

 Website

Your comment is 0 characters limited to 3000 characters.