windowsforms-107-controls-and-libraries-printing-exporting-examples-using-printing-links-how-to-create-a-custom-link-to-print-a-listview-control.md
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.
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.
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);
}
}
}
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
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:
The following code creates the content for the report’s page section in the marginal header area. It displays the current month and date.
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;
}
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
The following code creates the content for the report header section.
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);
}
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
The following code creates the content for the detail header report section.
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);
}
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
The following code adds ListView items to the Detail section.
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);
}
}
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
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.
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);
}
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
The following code creates the content for the report footer section.
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);
}
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
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.
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;
}
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:
using DevExpress.XtraPrinting;
using DevExpress.XtraPrintingLinks;
using UserLinks;
// ...
ListLink myLink = new ListLink(printingSystem1);
myLink.ListViewControl=listView1;
myLink.ShowPreview();
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