Printing GridView - page orientation and margins

9 posts, 0 answers
  1. Mike
    Mike avatar
    23 posts
    Member since:
    Jun 2012

    Posted 07 Dec 2012 Link to this post

    Hi,

    I am having some issues printing a grid view. The code I use to print is modified from the downloadable example. The issue is that the page orientation is always portrait, and the grid appears rotated 90 degrees on the page no top margin (see attached image, I printed to pdf). Instead, I would like the page in landscape mode, with proper margins. It also appears that if the grid view is wider than the page, new pages are not added, instead the values are cut off.

    So, my questions are:
    1. How can I change the page orientation when printing the grid view (programmatically)?
    2. How can I add margins?
    3. How can I print grid views that are wider than a page on multiple pages?

    Here is my code:

    In my context menu:
    //print
    MenuItem mprintGridItem = new MenuItem();
    mprintGridItem.Header = "Print Grid";
    mprintGridItem.Click += TelerikGridPrint;
    MainGrid.ContextMenu.Items.Add(mprintGridItem);

    my click handler (note, the grid was created completely in code and in the XAML pages constructor, was added to a stack panel as a child.

    private void TelerikGridPrint(object sender, object args)
    {
      try
      {
        TelerikGridDocumentCreatorModel.Print(telerikResults.GridControl);
      }
      catch (Exception ex)
      {
        Logger.LogError("TelerikGridPrint: " + ex);
      }
    }

    And my code to print:
    public static class TelerikGridDocumentCreatorModel // : DependencyObject, INotifyPropertyChanged
    {
      private static Color HeaderBackground = Color.FromArgb(255, 127, 127, 127);
      private static Color RowBackground = Color.FromArgb(255, 251, 247, 255);
      private static Color GroupHeaderBackground = Color.FromArgb(255, 216, 216, 216);
     
      public static void Print(object parameter)
      {
        RadGridView grid = (RadGridView)parameter;
        RadRichTextBox rtb = new RadRichTextBox() { Height = 0 };
     
        rtb.Name = "RadRichTextBox1";
     
        Grid parent = grid.ParentOfType<Grid>();
        if (parent != null && parent.FindName(rtb.Name) == null)
        {
          parent.Children.Add(rtb);
          rtb.ApplyTemplate();
        }
     
        rtb.Dispatcher.BeginInvoke((Action)(() =>
        {
          rtb.Document = CreateDocument(grid);
        }));
     
        PrintSettings pSettings = new PrintSettings();
     
        pSettings.DocumentName = "MyDocument";
        pSettings.PrintMode = PrintMode.Native;
        pSettings.PrintScaling = PrintScaling.None;
     
        rtb.Print(pSettings);
      }
     
      private static RadDocument CreateDocument(RadGridView grid)
      {
        List<GridViewBoundColumnBase> columns = (from c in grid.Columns.OfType<GridViewBoundColumnBase>()
                                                 orderby c.DisplayIndex
                                                 select c).ToList();
     
        Telerik.Windows.Documents.Model.Table table = new Telerik.Windows.Documents.Model.Table();
     
        RadDocument document = new RadDocument();
        Telerik.Windows.Documents.Model.Section section = new Telerik.Windows.Documents.Model.Section();
        Telerik.Windows.Documents.Model.Paragraph paragraph1 = new Telerik.Windows.Documents.Model.Paragraph();
        Telerik.Windows.Documents.Model.Paragraph paragraph2 = new Telerik.Windows.Documents.Model.Paragraph();
        section.Blocks.Add(paragraph1);
        section.Blocks.Add(table);
        section.Blocks.Add(paragraph2);
        document.Sections.Add(section);
     
        if (grid.ShowColumnHeaders)
        {
          Telerik.Windows.Documents.Model.TableRow headerRow = new Telerik.Windows.Documents.Model.TableRow();
     
          if (grid.GroupDescriptors.Count > 0)
          {
            Telerik.Windows.Documents.Model.TableCell indentCell = new Telerik.Windows.Documents.Model.TableCell();
            indentCell.PreferredWidth = new TableWidthUnit(grid.GroupDescriptors.Count * 20);
            indentCell.Background = HeaderBackground;
            headerRow.Cells.Add(indentCell);
          }
     
          for (int i = 0; i < columns.Count; i++)
          {
            Telerik.Windows.Documents.Model.TableCell cell = new Telerik.Windows.Documents.Model.TableCell();
            cell.Background = HeaderBackground;
            AddCellValue(cell, columns[i].UniqueName);
            cell.PreferredWidth = new TableWidthUnit((float)columns[i].ActualWidth);
            headerRow.Cells.Add(cell);
          }
     
          table.Rows.Add(headerRow);
        }
     
        if (grid.Items.Groups != null)
        {
          for (int i = 0; i < grid.Items.Groups.Count; i++)
          {
            AddGroupRow(table, grid.Items.Groups[i] as QueryableCollectionViewGroup, columns, grid);
          }
        }
        else
        {
          AddDataRows(table, grid.Items, columns, grid);
        }
     
        return document;
      }
     
      private static void AddDataRows(Telerik.Windows.Documents.Model.Table table, IList items, IList<GridViewBoundColumnBase> columns, RadGridView grid)
      {
        for (int i = 0; i < items.Count; i++)
        {
          Telerik.Windows.Documents.Model.TableRow row = new Telerik.Windows.Documents.Model.TableRow();
     
          if (grid.GroupDescriptors.Count > 0)
          {
            Telerik.Windows.Documents.Model.TableCell indentCell = new Telerik.Windows.Documents.Model.TableCell();
            indentCell.PreferredWidth = new TableWidthUnit(grid.GroupDescriptors.Count * 20);
            indentCell.Background = RowBackground;
            row.Cells.Add(indentCell);
          }
     
          for (int j = 0; j < columns.Count; j++)
          {
            Telerik.Windows.Documents.Model.TableCell cell = new Telerik.Windows.Documents.Model.TableCell();
     
            object value = columns[j].GetValueForItem(items[i]);
     
            AddCellValue(cell, value != null ? value.ToString() : string.Empty);
     
            cell.PreferredWidth = new TableWidthUnit((float)columns[j].ActualWidth);
            cell.Background = RowBackground;
     
            row.Cells.Add(cell);
          }
     
          table.Rows.Add(row);
        }
      }
     
      private static void AddGroupRow(Telerik.Windows.Documents.Model.Table table, QueryableCollectionViewGroup group, IList<GridViewBoundColumnBase> columns, RadGridView grid)
      {
        Telerik.Windows.Documents.Model.TableRow row = new Telerik.Windows.Documents.Model.TableRow();
     
        int level = GetGroupLevel(group);
        if (level > 0)
        {
          Telerik.Windows.Documents.Model.TableCell cell = new Telerik.Windows.Documents.Model.TableCell();
          cell.PreferredWidth = new TableWidthUnit(level * 20);
          cell.Background = GroupHeaderBackground;
          row.Cells.Add(cell);
        }
     
        Telerik.Windows.Documents.Model.TableCell aggregatesCell = new Telerik.Windows.Documents.Model.TableCell();
        aggregatesCell.Background = GroupHeaderBackground;
        aggregatesCell.ColumnSpan = columns.Count + (grid.GroupDescriptors.Count > 0 ? 1 : 0) - (level > 0 ? 1 : 0);
     
        AddCellValue(aggregatesCell, group.Key != null ? group.Key.ToString() : string.Empty);
     
        foreach (AggregateResult result in group.AggregateResults)
        {
          AddCellValue(aggregatesCell, result.FormattedValue != null ? result.FormattedValue.ToString() : string.Empty);
        }
     
        row.Cells.Add(aggregatesCell);
     
        table.Rows.Add(row);
     
        if (group.HasSubgroups)
        {
          foreach (var g in group.Subgroups)
          {
            AddGroupRow(table, g as QueryableCollectionViewGroup, columns, grid);
          }
        }
        else
        {
          AddDataRows(table, group.Items, columns, grid);
        }
      }
     
      private static void AddCellValue(Telerik.Windows.Documents.Model.TableCell cell, string value)
      {
        Telerik.Windows.Documents.Model.Paragraph paragraph = new Telerik.Windows.Documents.Model.Paragraph();
        cell.Blocks.Add(paragraph);
     
        Telerik.Windows.Documents.Model.Span span = new Telerik.Windows.Documents.Model.Span();
        span.Text = value;
     
        paragraph.Inlines.Add(span);
      }
     
      private static int GetGroupLevel(IGroup group)
      {
        int level = 0;
     
        IGroup parent = group.ParentGroup;
     
        while (parent != null)
        {
          level++;
          parent = parent.ParentGroup;
        }
     
        return level;
      }

  2. Mike
    Mike avatar
    23 posts
    Member since:
    Jun 2012

    Posted 07 Dec 2012 Link to this post

    Looking further into it, it seems that all document settings on the RadRichTextBox are ignored completeley.

    Doing this makes no changes:

    public static void Print(object parameter)
    {
      RadGridView grid = (RadGridView)parameter;
      RadRichTextBox rtb = new RadRichTextBox() { Height = 0 };
     
      rtb.Name = "RadRichTextBox1";
     
      Grid parent = grid.ParentOfType<Grid>();
      if (parent != null && parent.FindName(rtb.Name) == null)
      {
        parent.Children.Add(rtb);
        rtb.ApplyTemplate();
      }
     
      rtb.Dispatcher.BeginInvoke((Action)(() =>
      {
        rtb.Document = CreateDocument(grid);
      }));
     
      rtb.Document.SectionDefaultPageOrientation = PageOrientation.Landscape;
      rtb.Document.LayoutMode = DocumentLayoutMode.Paged;
      rtb.Document.SectionDefaultPageMargin = new Padding(50);
      rtb.Document.Measure(RadDocument.MAX_DOCUMENT_SIZE);
      rtb.Document.Arrange(new RectangleF(PointF.Empty, rtb.Document.DesiredSize));
      rtb.Document.SectionDefaultPageSize = PaperTypeConverter.ToSize(PaperTypes.A2);
     
      PrintSettings pSettings = new PrintSettings();
     
      rtb.Print("document", PrintMode.Native);
    }

    All the settings there for page orientation, page size, etc. are ignored. Am I doing something wrong?

    Using these same settings, I was able to export to PDF correctly.
  3. UI for WPF is Visual Studio 2017 Ready
  4. Mike
    Mike avatar
    23 posts
    Member since:
    Jun 2012

    Posted 07 Dec 2012 Link to this post

    I've also added this to the CreateDocument method, to no avail:

    section.PageOrientation = PageOrientation.Landscape;
    section.PageMargin = new Padding(50);
    section.PageSize = PaperTypeConverter.ToSize(PaperTypes.A2);


    I am using version 2012.3.1017.40. 
  5. Petya
    Admin
    Petya avatar
    975 posts

    Posted 12 Dec 2012 Link to this post

    Hi Mike,
    The code snippets in your first post do not contain any landscape, margin, etc. changes from the default ones, so I may be missing something, but here are my observation:
    The properties you wish to change are properties of Section.  SectionDefaultPageOrientation, SectionDefaultPageMargin, SectionDefaultPageSize properties of the RadDocument take effect on sections added after they are set (they defin the default values). That said, the proper way to change the values would be to apply them to the just-created section in the CreateDocument method. I tried that and it works okay at our end. Can you please verify once again what you said in your last post and get back to us?
    To your questions:
    1. Currently you can choose between Portrait and Landscape page orientation and indeed, the Landscape option rotates the page at 90 degrees. These are set using the corresponding properties of the Section.
    2. Margins are applied through the PageMargin property of Section.
    3. Unfortunately, there is no easy way to fix the clipped document elements. When a document element (such as a table) is too large to fit on one page it gets clipped. What you can do is implement a custom logic that will split the table when it is larger than the page area. I would suggest you look through the hierarchy of elements in RadDocument to help you achieve the scenario.

    I hope you'll find this information helpful. Let us know how it goes.

     
    Regards,
    Petya
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  6. Mike
    Mike avatar
    23 posts
    Member since:
    Jun 2012

    Posted 13 Dec 2012 Link to this post

    I haven't looked into point 1 or 2 yet, but for 3, how can I easily tell if a table is larger than the page area?
  7. Mike
    Mike avatar
    23 posts
    Member since:
    Jun 2012

    Posted 18 Dec 2012 Link to this post

    I've verified that indeed the section settings are being ignored. The settings are used when I export to PDF instead of adding to a RadRichTextBox and printing. When printing, if I manually change the print layout to landscape, it looks ok (the settings are still not respected, but the results look ok). However, the print dialog always pops up in portrait mode. 

    Because it looks proper exported to PDF, I can tell the RadDocument is formatted properly, but it seems that the RadRichTextBox printing just doesn't use them properly.
  8. Petya
    Admin
    Petya avatar
    975 posts

    Posted 18 Dec 2012 Link to this post

    Hello Mike,

    I am attaching the project I used for testing to this post. Can you please take a look at it and tell us the results it produces on your end?

    The first thing that comes to mind, although a long shot, is that some printers allow printing in poster (sometimes called mosaic) mode. That may allow you to set the paper size of your sections to one larger than A4 and let the printer handle the splitting for you.

    Overall, the scenario is complicated and I believe it falls a bit out of the scope of RadRichTextBox. What I can suggest is to turn to a product that specializes in such requirements like Reporting.
     
    Regards,
    Petya
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  9. band
    band avatar
    12 posts
    Member since:
    Jun 2016

    Posted 16 Aug Link to this post

    Using the example above, how would you set the table such that it'll create new column headers on new pages?
  10. Tanya
    Admin
    Tanya avatar
    402 posts

    Posted 18 Aug Link to this post

    Hello Band,

    There is a boolean property exposed by the TableRow class - RepeatOnEveryPage. More information on how to use this property is available in the Repeat Table Header Row article from our documentation. 

    You could find the creation of the Table object that represents the contents of the RadGridView in the TelerikGridDocumentCreatorModel class, more precisely - the CreateDocument() method.

    Hope this helps.

    Regards,
    Tanya
    Telerik by Progress
    Do you need help with upgrading your AJAX, WPF or WinForms project? Check the Telerik API Analyzer and share your thoughts.
Back to Top
UI for WPF is Visual Studio 2017 Ready