Back to Devexpress

How to: Create a Custom Link to Print a ListView Control

windowsforms-107-controls-and-libraries-printing-exporting-examples-using-printing-links-how-to-create-a-custom-link-to-print-a-listview-control.md

latest13.3 KB
Original Source

How to: Create a Custom Link to Print a ListView Control

  • Sep 26, 2023
  • 6 minutes to read

This topic explains how to create your own link to print specific objects that do not provide the IPrintable interface, or the appropriate printing link exists in the XtraPrinting Library.

The Printing Links technology implemented in XtraPrinting Library enables you to generate reports for any given object, even if it has no visual representation - for instance, a dataset. To accomplish this, you need a Link to print a specific object. This Link should be inherited from the base Link class. Once implemented, the Link can be used to print the object in any of your projects, without the need to write any new code.

We’ll examine the steps to create your own Link to print a standard ListView control.

Step 1. Create a New Project and Provide Mandatory Declarations

Start a new Windows Control Library project in Microsoft Visual Studio. Implement the following code to declare a new link in the UserLinks namespace, then override the standard Link class constructors and the Link.CreateDocument method.

csharp
using DevExpress.XtraPrinting;
using DevExpress.XtraPrintingLinks;
// ...

namespace UserLinks {
    public class ListLink : DevExpress.XtraPrinting.Link {
        private ListView listView = null;

        public ListView ListViewControl { get { return listView; } set { listView = value; } 
        } 

        public ListLink(System.ComponentModel.IContainer container) : base(container) {
        }

        public ListLink() : base() {
        }

        public ListLink(PrintingSystem ps) : base(ps) {
        }

        public override void CreateDocument(PrintingSystem ps) {
            if (listView == null) return;
            if (listView.Items.Count == 0) return;
            BrickGraphics gr = ps.Graph;
            base.CreateDocument(ps);
        }   
    }
}
vb
Imports DevExpress.XtraPrinting
Imports DevExpress.XtraPrintingLinks
' ...

Namespace UserLinks
    Public Class ListLink
    Inherits DevExpress.XtraPrinting.Link
        Private listView As ListView = Nothing

        Public Property ListViewControl() As ListView
            Get
                Return listView
            End Get
            Set
                listView = Value
            End Set
        End Property

        Public Sub New(ByVal container As System.ComponentModel.IContainer)
            MyBase.New(container)
        End Sub

        Public Sub New()
            MyBase.New()
        End Sub

        Public Sub New(ByVal ps As PrintingSystem)
            MyBase.New(ps)
        End Sub

        Public Overrides Overloads Sub CreateDocument(ByVal ps As PrintingSystem)
            If listView Is Nothing Then Return
            If listView.Items.Count = 0 Then Return
            Dim gr As BrickGraphics = ps.Graph
            MyBase.CreateDocument(ps)
        End Sub
    End Class
End Namespace

Step 2. Create Custom Report Sections

You don’t need to provide methods for all possible page areas. At a minimum, the Detail area creation method is enough.

The report page sections are shown in the following picture:

2.1. MarginalHeader Page Section

The following code creates the content for the report’s page section in the marginal header area. It displays the current month and date.

csharp
protected override void CreateMarginalHeader(BrickGraphics gr) {
    gr.Modifier = BrickModifier.MarginalHeader;
    string format = "Printed on {0:MMMM, dd}";
    PageInfoBrick brick = gr.DrawPageInfo(PageInfo.DateTime, format, Color.Black, 
    new RectangleF(0, 0, 0, 20), BorderSide.None);
    brick.Alignment = BrickAlignment.Far;
    brick.AutoWidth = true;
}
vb
Protected Overrides Overloads Sub CreateMarginalHeader(ByVal gr As BrickGraphics)
    gr.Modifier = BrickModifier.MarginalHeader
    Dim format As String = "Printed on {0:MMMM, dd}"
    Dim brick As PageInfoBrick = gr.DrawPageInfo(PageInfo.DateTime, format, Color.Black, _ 
        New RectangleF(0, 0, 0, 20), BorderSide.None)
    brick.Alignment = BrickAlignment.Far
    brick.AutoWidth = True
End Sub

2.2. ReportHeader Page Section

The following code creates the content for the report header section.

csharp
protected override void CreateReportHeader(BrickGraphics gr) {
    gr.Modifier = BrickModifier.ReportHeader;
    TextBrick textBrick;
    gr.BackColor = Color.White;
    gr.StringFormat = new BrickStringFormat(StringFormatFlags.NoWrap | StringFormatFlags.LineLimit);
    gr.StringFormat = gr.StringFormat.ChangeAlignment(StringAlignment.Center);
    Rectangle r = new Rectangle(0, 0, 200, 30);
    gr.Font = new Font("Arial", 16);
    textBrick = gr.DrawString("ListView Report", Color.Red, r, BorderSide.None);
    textBrick.StringFormat.ChangeAlignment(StringAlignment.Center);
}
vb
Protected Overrides Overloads Sub CreateReportHeader(ByVal gr As BrickGraphics)
    gr.Modifier = BrickModifier.ReportHeader
    Dim textBrick As TextBrick
    gr.BackColor = Color.White
    gr.StringFormat = New BrickStringFormat(StringFormatFlags.NoWrap Or StringFormatFlags.LineLimit)
    gr.StringFormat = gr.StringFormat.ChangeAlignment(StringAlignment.Center)
    Dim r As Rectangle = New Rectangle(0, 0, 200, 30)
    gr.Font = New Font("Arial", 16)
    textBrick = gr.DrawString("ListView Report", Color.Red, r, BorderSide.None)
    textBrick.StringFormat.ChangeAlignment(StringAlignment.Center)
End Sub

2.3. DetailHeader Page Section

The following code creates the content for the detail header report section.

csharp
protected override void CreateDetailHeader(BrickGraphics gr) {
    if (listView.View != View.Details)
        return;
    gr.Modifier = BrickModifier.DetailHeader;
    gr.Font = listView.Font;
    gr.BackColor = SystemColors.Control;
    gr.ForeColor = SystemColors.ControlText;
    gr.StringFormat = new BrickStringFormat(StringFormatFlags.NoWrap);
    gr.StringFormat = gr.StringFormat.ChangeAlignment(StringAlignment.Near);
    gr.DrawString("Name", gr.ForeColor, listView.Items[0].Bounds, BorderSide.All);
}
vb
Protected Overrides Overloads Sub CreateDetailHeader(ByVal gr As BrickGraphics)
    If listView.View <> View.Details Then Return
    gr.Modifier = BrickModifier.DetailHeader
    gr.Font = listView.Font
    gr.BackColor = SystemColors.Control
    gr.ForeColor = SystemColors.ControlText
    gr.StringFormat = New BrickStringFormat(StringFormatFlags.NoWrap)
    gr.StringFormat = gr.StringFormat.ChangeAlignment(StringAlignment.Near)
    gr.DrawString("Name", gr.ForeColor, listView.Items(0).Bounds, BorderSide.All)
End Sub

2.4. Detail Page Section

The following code adds ListView items to the Detail section.

csharp
protected override void CreateDetail(BrickGraphics gr) {
    gr.StringFormat = new BrickStringFormat(StringFormatFlags.NoWrap | 
        StringFormatFlags.LineLimit);

    gr.StringFormat = gr.StringFormat.ChangeLineAlignment(StringAlignment.Near);

    for (int i = 0; i < listView.Items.Count; i++) {
        gr.Font = listView.Items[i].Font;
        gr.BackColor = listView.Items[i].BackColor;
        gr.ForeColor = listView.Items[i].ForeColor;
        gr.DrawString(listView.Items[i].Text, gr.ForeColor, listView.Items[i].Bounds, 
            BorderSide.None);
    }
}
vb
Protected Overrides Overloads Sub CreateDetail(ByVal gr As BrickGraphics)
    gr.StringFormat = New BrickStringFormat(StringFormatFlags.NoWrap Or _
        StringFormatFlags.LineLimit)

    gr.StringFormat = gr.StringFormat.ChangeLineAlignment(StringAlignment.Near)

    Dim i As Integer = 0

    Do While i < listView.Items.Count
        gr.Font = listView.Items(i).Font
        gr.BackColor = listView.Items(i).BackColor
        gr.ForeColor = listView.Items(i).ForeColor
        gr.DrawString(listView.Items(i).Text, gr.ForeColor, listView.Items(i).Bounds, _ 
            BorderSide.None)
        i += 1
    Loop
End Sub

2.5. DetailFooter Page Section

The following code creates the content for the detail footer report section using the ListView settings. It displays the number of items in the ListView control.

csharp
protected override void CreateDetailFooter(BrickGraphics gr) {
    gr.Modifier = BrickModifier.DetailFooter;
    gr.Font = listView.Font;
    gr.BackColor = SystemColors.Control;
    gr.ForeColor = SystemColors.ControlText;
    gr.StringFormat = new BrickStringFormat(StringFormatFlags.NoWrap);
    gr.StringFormat = gr.StringFormat.ChangeAlignment(StringAlignment.Far);
    gr.DrawString("Total Items: " + Convert.ToString(listView.Items.Count), gr.ForeColor, 
        new Rectangle(0, 0, 60 + listView.Items[0].Bounds.Width, listView.Items[0].Bounds.Height), 
        BorderSide.All);
}
vb
Protected Overrides Overloads Sub CreateDetailFooter(ByVal gr As BrickGraphics)
    gr.Modifier = BrickModifier.DetailFooter
    gr.Font = listView.Font
    gr.BackColor = SystemColors.Control
    gr.ForeColor = SystemColors.ControlText
    gr.StringFormat = New BrickStringFormat(StringFormatFlags.NoWrap)
    gr.StringFormat = gr.StringFormat.ChangeAlignment(StringAlignment.Far)
    gr.DrawString("Total Items: " & Convert.ToString(listView.Items.Count), gr.ForeColor, _ 
        New Rectangle(0, 0, 60 + listView.Items(0).Bounds.Width, listView.Items(0).Bounds.Height), _
    BorderSide.All)
End Sub

2.6. ReportFooter Page Section

The following code creates the content for the report footer section.

csharp
protected override void CreateReportFooter(BrickGraphics gr) {
    gr.Modifier = BrickModifier.ReportFooter;

    gr.StringFormat = new BrickStringFormat(StringFormatFlags.NoWrap | 
        StringFormatFlags.LineLimit);
    gr.StringFormat = gr.StringFormat.ChangeLineAlignment(StringAlignment.Far);

    gr.Font = listView.Font;

    gr.DrawString("Created by John Smith", gr.ForeColor, new Rectangle(0, 0, 200, 30), 
        BorderSide.None);
}
vb
Protected Overrides Overloads Sub CreateReportFooter(ByVal gr As BrickGraphics)

    gr.Modifier = BrickModifier.ReportFooter

    gr.StringFormat = New BrickStringFormat(StringFormatFlags.NoWrap Or _
        StringFormatFlags.LineLimit)
    gr.StringFormat = gr.StringFormat.ChangeLineAlignment(StringAlignment.Far)

    gr.Font = listView.Font

    gr.DrawString("Created by John Smith", gr.ForeColor, New Rectangle(0, 0, 200, 30), _
        BorderSide.None)
End Sub

2.7. MarginalFooter Page Section

The following code creates the content for the report’s page section in the marginal footer area. It displays the page number and total number of pages in the report.

csharp
protected override void CreateMarginalFooter(BrickGraphics gr) {
    gr.Modifier = BrickModifier.MarginalFooter;
    string format = "Page {0} of {1}";
    PageInfoBrick brick = gr.DrawPageInfo(PageInfo.NumberOfTotal, format, Color.Black, 
        new RectangleF(0, 0, 0, 20), BorderSide.None);
    brick.Alignment = BrickAlignment.Far;
    brick.AutoWidth = true;
}
vb
Protected Overrides Overloads Sub CreateMarginalFooter(ByVal gr As BrickGraphics)
    gr.Modifier = BrickModifier.MarginalFooter
    Dim format As String = "Page {0} of {1}"
    Dim brick As PageInfoBrick = gr.DrawPageInfo(PageInfo.NumberOfTotal, format, Color.Black, _ 
    New RectangleF(0, 0, 0, 20), BorderSide.None)
    brick.Alignment = BrickAlignment.Far
    brick.AutoWidth = True
End Sub

A custom link is now finished, and once the assembly is correctly referenced, you can use the custom printing link in your application as follows:

csharp
using DevExpress.XtraPrinting;
using DevExpress.XtraPrintingLinks;
using UserLinks;
// ...

    ListLink myLink = new ListLink(printingSystem1);
    myLink.ListViewControl=listView1;
    myLink.ShowPreview();
vb
Imports DevExpress.XtraPrinting
Imports DevExpress.XtraPrintingLinks
Imports UserLinks
' ...

    Private myLink As ListLink = New ListLink(printingSystem1)
    Private myLink.ListViewControl=listView1
    myLink.ShowPreview()

See Also

How to: Create a Printable ListView Descendant Implementing the IPrintable Interface