I'm trying to implement a WPF Print function. It's working as long as the user doesnt want to print more than fits to one page. My Application enables the user to create xaml in runtime. Now i want to also enable him to print the xaml controls he created.
I have checked the total height of all xaml controls, devided by the pageheight and ceiled that number, so i know how many pages i have to print.
Next I'm creating a List of FrameworkElements for each page (see logic below) and store every List (each stands for one page) in an array.
At the end i want to create a preview which contains every page and enables the user to print all pages. In order to do that i have to put the pages together to a Document, but i dont know how. Please take a look at my code:
Package package = Package.Open("test.xps", FileMode.Create);
// Create new xps document based on the package opened
XpsDocument doc = new XpsDocument(package);
// Create an instance of XpsDocumentWriter for the document
XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(doc);
// Write the canvas (as Visual) to the document
double height = element.ActualHeight;
double width = element.ActualWidth;
System.Windows.Controls.PrintDialog printDlg = new System.Windows.Controls.PrintDialog();
Size pageSize = new Size(printDlg.PrintableAreaWidth, printDlg.PrintableAreaHeight);
int pageCount = (int)Math.Ceiling(height / pageSize.Height);
if (pageSize.Height < height) {
var grid = element as Grid;
var children = grid.Children;
List<FrameworkElement>[] pages = new List<FrameworkElement>[pageCount-1];
int i = 0;
double currentHeight = 0;
foreach (FrameworkElement c in children) {
currentHeight += c.RenderSize.Height;
if (currentHeight < pageSize.Height) {
pages[i] = new List<FrameworkElement>();
pages[i].Add(c);
}
else {
i++;
currentHeight = 0;
pages[i] = new List<FrameworkElement>();
pages[i].Add(c);
}
}
for (int j = 0; j < pageCount; j++) {
var collator = writer.CreateVisualsCollator();
collator.BeginBatchWrite();
foreach (FrameworkElement c in pages[j]) {
collator.Write(c);
}
collator.EndBatchWrite();
}
}
doc.Close();
package.Close();
string filename = #"C:\Users\rzimmermann\Documents\Visual Studio 2012\Projects\MvvmLightPrintFunction\MvvmLightPrintFunction\bin\Debug\test.xps";
DocumentViewer viewer = new DocumentViewer();
doc = new XpsDocument(filename, FileAccess.Read);
viewer.Document = doc.GetFixedDocumentSequence();
Window ShowWindow = new Window();
ShowWindow.Width = 400;
ShowWindow.Height = 300;
ShowWindow.Content = viewer;
ShowWindow.Show();
#kenny is right you need to use the FixedPages. For a great tutorial pleas see: http://www.nbdtech.com/Blog/archive/2009/04/20/wpf-printing-part-2-the-fixed-document.aspx
As far as adding pages to a document you can do it like so:
doc.Pages.Add(page1Content);
doc.Pages.Add(page2Content);
//ect.
... PrintDialog dialog = new PrintDialog();
//dialog.PrintVisual(this.scrollCheckCardinfo, "");
Nullable<Boolean> print = dialog.ShowDialog();
if (print == true)
{
Grid DynamicGrid = new Grid();
DynamicGrid.Margin = new Thickness(100, 50, 0, 0);
RowDefinition gridRow1 = new RowDefinition();
gridRow1.Height = new GridLength(45);
RowDefinition gridRow2 = new RowDefinition();
DynamicGrid.RowDefinitions.Add(gridRow1);
DynamicGrid.RowDefinitions.Add(gridRow2);
TextBlock txtBlock1 = new TextBlock();
txtBlock1.Text = "Printed by xyz " + DateTime.Now.ToString();
txtBlock1.FontSize = 14;
txtBlock1.FontWeight = FontWeights.Bold;
txtBlock1.VerticalAlignment = VerticalAlignment.Top;
Grid.SetRow(txtBlock1, 0);
Grid.SetRow(this.scrollCheckCardinfo, 1);
DynamicGrid.Children.Add(txtBlock1);
DynamicGrid.Children.Add(CloneXaml(this.scrollCheckCardinfo));
dialog.PrintVisual(DynamicGrid, "xyz");
}...
public static T CloneXaml<T>(T source)
{
string xaml = XamlWriter.Save(source);
StringReader sr = new StringReader(xaml);
XmlReader xr = XmlReader.Create(sr);
return (T)XamlReader.Load(xr);
}
this.scrollCheckCardinfo is a Grid.
Related
I have C# project already done but im having issue with printing it's charts when comes out with more pages of data points, i got the scroll bar work when start getting more pages so the user can review all data on all pages but i could not find how to make the print preview shows them or print them,
when click on print, it shows only the first page on the print preview and same thing when print it out.
her is the print code:
PrintPreviewDialog ppd = new PrintPreviewDialog();
ppd.Document = this.chart1.Printing.PrintDocument;
((Form)ppd).WindowState = FormWindowState.Maximized;
chart1.Printing.PrintDocument.DefaultPageSettings.Landscape = true;
chart1.Printing.PrintDocument.DefaultPageSettings.Margins.Left = 0;
chart1.Printing.PrintDocument.DefaultPageSettings.Margins.Right = 0;
chart1.Printing.PrintDocument.DefaultPageSettings.Margins.Top = 0;
chart1.Printing.PrintDocument.DefaultPageSettings.Margins.Bottom = 0;
ppd.ShowDialog();
and here is the chart load code:
public void loadChart(string sqlvalue)//load chart method
{
chart1.ChartAreas[0].AxisY.Maximum = 55;
chart1.ChartAreas[0].AxisY.Minimum = 35;
chart1.ChartAreas[0].AxisY.Interval = 5;//control how many lines/Interval
chart1.ChartAreas[0].AxisY.ScrollBar.Enabled = true;
chart1.ChartAreas[0].AxisY.ScaleView.Zoomable = true;
chart1.ChartAreas[0].AxisX.Minimum = 0;
// chart1.ChartAreas[0].AxisX.Maximum = 10;
chart1.ChartAreas[0].AxisX.Interval = 1;
//X AXES label angle
chart1.ChartAreas[0].AxisX.LabelStyle.Angle = 60;
da = new SqlDataAdapter(sqlvalue, cn.connect());
da.Fill(dt);
this.chart1.DataSource = dt;
this.chart1.Series["left"].XValueMember = dt.Columns[3].ToString();//date data
this.chart1.Series["left"].YValueMembers = dt.Columns[1].ToString();//spindle 1 data
this.chart1.Series["Right"].YValueMembers = dt.Columns[2].ToString();//spindle 2 data
//label the series lines, Backcolor and forcolor
chart1.Series[0].LabelBackColor = Color.Red;
chart1.Series[0].LabelForeColor = Color.White;
//datapoint marker's color, bordercolor,style and size
chart1.Series[0].MarkerColor = Color.White;
chart1.Series[0].MarkerBorderColor = Color.Black;
chart1.Series[0].MarkerStyle = MarkerStyle.Circle;
chart1.Series[0].MarkerSize = 8;
//datapoint marker's color, style and size
chart1.Series[1].MarkerColor = Color.White;
chart1.Series[1].MarkerBorderColor = Color.Black;
chart1.Series[1].MarkerStyle = MarkerStyle.Circle;
chart1.Series[1].MarkerSize = 8;
chart1.Series[1].LabelBackColor = Color.Blue;
chart1.Series[1].LabelForeColor = Color.White;
//Chart background lines color
chart1.ChartAreas[0].AxisX.MajorGrid.LineColor = Color.Silver;
chart1.ChartAreas[0].AxisY.MajorGrid.LineColor = Color.Silver;
this.chart1.DataBind();
cn.disconnect();
// enable autoscroll
chart1.ChartAreas[0].CursorX.AutoScroll = true;//------------
chart1.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
chart1.ChartAreas[0].AxisX.ScaleView.Zoom(0, 15);
chart1.ChartAreas[0].AxisX.ScrollBar.ButtonStyle = ScrollBarButtonStyles.SmallScroll;
// set scrollbar small change to the target size
chart1.ChartAreas[0].AxisX.ScaleView.SmallScrollSize = 15;
Legend left = new Legend();
Legend LC = CustomCloneLegend(chart1, left);
chart1.Legends.Add(LC);
chart1.Padding = Padding.Empty;
ChartArea CA = chart1.ChartAreas[0];
CA.Position = new ElementPosition(4,6, 100, 90);
}
Thank you for your time and help, here is the chart code update:
private static Image MergeImages(List<Image> imageList)
{
var finalSize = new Size();
foreach (var image in imageList)
{
if (image.Width > finalSize.Width)
{
finalSize.Width = image.Width;
}
finalSize.Height += image.Height;
}
var outputImage = new Bitmap(finalSize.Width, finalSize.Height);
using (var gfx = Graphics.FromImage(outputImage))
{
var y = 0;
foreach (var image in imageList)
{
gfx.DrawImage(image, 0, y);
y += image.Height;
}
}
return outputImage;
}
The second method:
List<Image> ChartsToImages(List<Chart> charts)
{
var imageList = new List<Image>();
foreach (var c in charts)
{
using (var ms = new MemoryStream())
{
c.SaveImage(ms, ChartImageFormat.Png);
var bmp = System.Drawing.Bitmap.FromStream(ms);
imageList.Add(bmp);
}
}
return imageList;
}
and this code
var chartList = new List<Chart> { chart1 };
var imageList = ChartsToImages(chartList);
var finalImage = MergeImages(imageList);
finalImage.Save("D:\\Junk.png", ImageFormat.Png);
Im not sure is that what you mean by your first comment, but i found this code here under Converting chart to image questions. this code convert and saves the chart in the same amount of pages but i need to show them in the printpreviewcontrol and print them.
Below code refers to the as per page count starting point and ending point based printing. And Grid view value chars are row loop based counting the page.
private int numberOfItemsPerPage = 0;
private int numberOfItemsPrintedSoFar = 0;
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
int height = 480; //page height stating point
for (int l = numberOfItemsPrintedSoFar; l < dataGridView2.Rows.Count; l++)
{
numberOfItemsPerPage = numberOfItemsPerPage + 1;
if (numberOfItemsPerPage <= 25) // 25 is Page Line Item
{
numberOfItemsPrintedSoFar++;
if (numberOfItemsPrintedSoFar <= dataGridView2.Rows.Count)
{
height += dataGridView2.Rows[0].Height;
e.Graphics.DrawString(dataGridView2.Rows[l].Cells[0].FormattedValue.ToString(), dataGridView2.Font = new Font("Book Antiqua", 8), Brushes.Black, new RectangleF(5, height, dataGridView2.Columns[0].Width, dataGridView2.Rows[0].Height));
e.Graphics.DrawString(dataGridView2.Rows[l].Cells[1].FormattedValue.ToString(), dataGridView2.Font = new Font("Book Antiqua", 8), Brushes.Black, new RectangleF(170, height, dataGridView2.Columns[0].Width, dataGridView2.Rows[0].Height));
e.Graphics.DrawString(dataGridView2.Rows[l].Cells[2].FormattedValue.ToString(), dataGridView2.Font = new Font("Book Antiqua", 8), Brushes.Black, new RectangleF(290, height, dataGridView2.Columns[0].Width, dataGridView2.Rows[0].Height));
e.Graphics.DrawString(dataGridView2.Rows[l].Cells[3].FormattedValue.ToString(), dataGridView2.Font = new Font("Book Antiqua", 8), Brushes.Black, new RectangleF(345, height, dataGridView2.Columns[0].Width, dataGridView2.Rows[0].Height));
}
else
{
e.HasMorePages = false;
}
}
else
{
numberOfItemsPerPage = 0;
e.HasMorePages = true;
return;
}
}
numberOfItemsPerPage = 0;
numberOfItemsPrintedSoFar = 0;
}
How can I export the “stamp annotation from image” to an image file?
I have a pdf which contains stamp annotions (in fact it's an image), I want to export all these kinds of images to file and get the x/y position.
I am new to pdf. Any idea or code will be appreciated.
[--- Edited on 2019/08/08 ---]
private void btnExtractAnnotaion_Click(object sender, EventArgs e)
{
PdfReader reader = new PdfReader(this.txtPdf.Text);
PdfDictionary pageDict = reader.GetPageN(reader.NumberOfPages);
PdfArray annotArray = pageDict.GetAsArray(PdfName.ANNOTS);
PdfObject annot = null;
Console.WriteLine("Annotation count:{0}", annotArray.Size);
for (int i = 0; i < annotArray.Size; i++)
{
annot = annotArray.GetDirectObject(i);
Console.WriteLine(annot.ToString());
//curAnnot = annotArray.GetAsDict(i);
//Console.WriteLine(curAnnot.ToString());
bool btmp = annot.IsDictionary();
if (btmp)
{
PdfDictionary pdfDic = ((PdfDictionary)annot);
PdfName stamp = pdfDic.GetAsName(PdfName.SUBTYPE);
if (stamp.Equals(PdfName.STAMP))
{
//PdfObject img = pdfDic.GetDirectObject(PdfName.RECT);
// How Can I get the image(png, jpg...) of Stamp?
}
}
iText7 is exactly the thing you want to use for that. ;)
https://www.nuget.org/packages/itext7/
https://itextpdf.com/en/products/itext-7
This is how you could get access to the stamps, depending on the stamping technique used:
using (PdfReader r = new PdfReader("input.pdf"))
using (PdfDocument doc = new PdfDocument(r))
{
var annotations = doc.GetPage(1).GetAnnotations();
}
on other occasions this could do the trick:
using (PdfReader r = new PdfReader("input.pdf"))
using (PdfDocument doc = new PdfDocument(r))
{
var res = doc.GetFirstPage().GetResources();
}
unless you provide a demo-pdf, that all the help i can give you
#mkl #FastJack Thanks for your time!
By this answer ImageRenderListener
It solved my problem. The following are my codes:
PdfReader reader = new PdfReader(this.txtPdf.Text);
PdfDictionary pageDict = reader.GetPageN(reader.NumberOfPages);
PdfArray annotArray = pageDict.GetAsArray(PdfName.ANNOTS);
//Console.WriteLine("Annotation count:{0}", annotArray.Size);
for (int i = 0; i < annotArray.Size; i++)
{
PdfObject annot = annotArray.GetDirectObject(i);
//Console.WriteLine(annot.ToString());
bool btmp = annot.IsDictionary();
if (btmp)
{
PdfDictionary pdfDic = ((PdfDictionary)annot);
PdfName stamp = pdfDic.GetAsName(PdfName.SUBTYPE);
if (stamp.Equals(PdfName.STAMP))
{
// rects are laid out [llx, lly, urx, ury]
float x, y, width, height;
PdfArray rect = pdfDic.GetAsArray(PdfName.RECT);
x = rect.GetAsNumber(0).FloatValue;
y = rect.GetAsNumber(1).FloatValue;
width = rect.GetAsNumber(2).FloatValue - x;
height = rect.GetAsNumber(3).FloatValue - y;
PdfDictionary appearancesDic = pdfDic.GetAsDict(PdfName.AP);
PdfStream normalAppearance = appearancesDic.GetAsStream(PdfName.N);
PdfDictionary resourcesDic = ormalAppearance.GetAsDict(PdfName.RESOURCES);
ImageRenderListener listener = new ImageRenderListener();
PdfContentStreamProcessor processor = new PdfContentStreamProcessor(listener);
processor.ProcessContent(
ContentByteUtils.GetContentBytesFromContentObject(normalAppearance), resourcesDic);
System.Drawing.Image drawingImage = listener.Images.First();
//Image image = Image.GetInstance(drawingImage, drawingImage.RawFormat);
}
}
}
My requirement is to print the details in landscape,not the page rotation.i need content printed in landscape.
Document doc = new Document(iTextSharp.text.PageSize.A4, (float)MarginLeft, (float)MarginRight, (float)MarginTop, (float)MarginBottom);
//210 mm width * 297 mm height
PaperWidthAvailable = iTextSharp.text.Utilities.MillimetersToPoints(210f) - ((float)MarginLeft + (float)MarginRight);
PaperHeightAvailable = iTextSharp.text.Utilities.MillimetersToPoints(297f) - ((float)MarginTop + (float)MarginBottom);
wdtOFcell = (float)BarcodeWidth + (float)BarcodeSpaceHorizontal;
colNo = (int)Math.Floor(PaperWidthAvailable / wdtOFcell);
TableWidth = wdtOFcell * colNo;
htOFcell = (float)BarcodeHeight + (float)BarcodeSpaceVertical;
PdfWriter writer = PdfWriter.GetInstance(doc, memStream);
doc.Open();
int noOfColumns = colNo;
// int additionalRow = imageBarcodeLists.Count % noOfColumns;
int i = 1;
PdfPTable table = new PdfPTable(noOfColumns);
table.DefaultCell.Border = iTextSharp.text.Rectangle.NO_BORDER;
table.HorizontalAlignment = 0;
table.TotalWidth = TableWidth;
table.LockedWidth = true;
float[] widths = new float[colNo];
for (int j = 0; j < colNo; j++)
{
widths[j] = wdtOFcell;
}
table.SetWidths(widths);
iTextSharp.text.Image itextBarcodeImage = null;
foreach (System.Drawing.Image barcodeImage in imageBarcodeLists)
{
var imageCompressor = new ImageCompressionUtility();
System.Drawing.Image barcodeImages = imageCompressor.TrimImageWhiteSpacesFromImage(barcodeImage);
itextBarcodeImage = iTextSharp.text.Image.GetInstance(barcodeImages, BaseColor.BLUE);
itextBarcodeImage.ScaleAbsolute((float)BarcodeWidth, (float)BarcodeHeight);
PdfPCell cells = new PdfPCell(itextBarcodeImage);
cells.Border = iTextSharp.text.Rectangle.NO_BORDER;
cells.PaddingTop = 0f;
cells.PaddingRight = 0f;
cells.PaddingBottom = 0f;
cells.PaddingLeft = 0f;
cells.UseAscender = true;
cells.FixedHeight = htOFcell;
cells.BackgroundColor = BaseColor.WHITE;
cells.Border = iTextSharp.text.Rectangle.NO_BORDER;
table.AddCell(cells);
i++;
}
doc.Add(table);
doc.Close();
The constant iTextSharp.text.PageSize.A4 is actually a Rectangle that is created like this:
public static readonly Rectangle A4 = new Rectangle(595,842);
If you want to rotate the page, you can use the Rotate() method as explained in my answer to this question: How to print custom page size as portrait in itextsharp
However, based on your comment "it rotates only the paper not the content written", you may be looking for a page size that is created like this:
Rectangle myA4 = new Rectangle(842,595);
Document doc = new Document(myA4);
If that doesn't work, please take a look at my answer to the question iText - Rotate page content while creating PDF
In that answer, I introduce a page rotation using a page event:
public class MyPdfPageEvent : iTextSharp.text.pdf.PdfPageEventHelper
{
public override void OnEndPage(PdfWriter writer, Document document)
{
writer.AddPageDictEntry(PdfName.ROTATE, PdfPage.SEASCAPE);
}
}
If none of the above has the effect you desire, you should improve your question (or it will be closed as "unclear what is asked").
i need to print a small report using PrintVisual function like following:
uc.DataContext = myDataTable.DefaultView; // us is UserControl
PrintDialog pDialog = new PrintDialog();
pDialog.PageRangeSelection = PageRangeSelection.AllPages;
pDialog.UserPageRangeEnabled = true;
pDialog.PrintQueue = System.Printing.LocalPrintServer.GetDefaultPrintQueue();
pDialog.PrintTicket = pDialog.PrintQueue.DefaultPrintTicket;
pDialog.PrintTicket.PageScalingFactor = 1;
System.Printing.PrintCapabilities capabilities = null;
try
{
capabilities = pDialog.PrintQueue.GetPrintCapabilities();
}
catch
{
capabilities = null;
}
Viewbox vb = new Viewbox();
vb.Child = uc;
System.Windows.Size sz = new Size(520, 380);
vb.MinWidth = 1;
vb.MinHeight = 1;
vb.Measure(sz);
vb.Arrange(new System.Windows.Rect(new System.Windows.Point(capabilities.PageImageableArea.OriginWidth, capabilities.PageImageableArea.OriginHeight), sz));
double scale = 1;
vb.LayoutTransform = new ScaleTransform(scale, scale);
pDialog.PrintVisual(vb, "MyViewBox");
the code works well in Win 8 and win 10 but not on win 7
any suggestions ?
So in our Report we have an ImageBox in the Detail Band which we want to have a different image per page.
Seeing that changing it in the BeforePrint Event of the Detail Band doesn't work (since it's only called once per print of the Report) I followed the following approach so far (which doesn't work):
In the PrintOnPage Event of a label of the Page Header Band of the Report (in order to have it called per page and be able to use the PrintOnPageEventArgs in the new XRPictureBox - I need the PageIndex):
private void xrLabel10_PrintOnPage(object sender, PrintOnPageEventArgs e)
{
this.Detail.Controls.Remove(xrPictureBox1); //Existing PictureBox control
this.Detail.Controls.Add(PictureBox(e));
}
Which calls this:
private List<Bitmap> _imageList;
public XRPictureBox PictureBox(PrintOnPageEventArgs e)
{
XRPictureBox pictureBox = new XRPictureBox();
var articleService = DependencyResolver.Current.GetService<IArticleService>();
int width;
int height;
pictureBox.Name = "xrPictureBox_" + e.PageIndex;
pictureBox.BackColor = Color.Transparent;
pictureBox.Dpi = 254F;
pictureBox.LocationFloat = new DevExpress.Utils.PointFloat(108.4792F, 71.4375F);
pictureBox.Name = "xrPictureBox_" + e.PageIndex;
pictureBox.SizeF = new SizeF(950F, 1225F);
pictureBox.Sizing = ImageSizeMode.Squeeze;
pictureBox.StylePriority.UseBackColor = false;
if (ReportUnit == ReportUnit.HundredthsOfAnInch)
{
width = (int)(GraphicsUnitConverter.Convert(xrPictureBox1.Size.Width, GraphicsUnit.Inch, GraphicsUnit.Pixel) / 100);
height = (int)(GraphicsUnitConverter.Convert(xrPictureBox1.Size.Height, GraphicsUnit.Inch, GraphicsUnit.Pixel) / 100);
}
else
{
width = (int)(GraphicsUnitConverter.Convert(xrPictureBox1.Size.Width, GraphicsUnit.Millimeter, GraphicsUnit.Pixel) / 10);
height = (int)(GraphicsUnitConverter.Convert(xrPictureBox1.Size.Height, GraphicsUnit.Millimeter, GraphicsUnit.Pixel) / 10);
}
if (_imageList == null)
{
_imageList = articleService .GetListOfImages((int)articleId.Value, width, height, PageColor); //this gets a List<Bitmap>
}
if (_imageList[e.PageIndex] == null)
return null;
pictureBox.Image = _imageList[e.PageIndex];
return pictureBox;
}
So basically my idea was to replace the existing Control with a new XRPictureBox with the new image. But it just doesn't appear in the Report, even though while debugging I see the code being run and retrieving the correct images for the correct pages.
Edit: nempoBu4's answer is correct generally, but unfortunately I failed to clarify an additional issue which makes it not perfect for my situation:
The report also has a subreport right next to the PictureBox and this subreport can expand to more than one pages. We wanted the PictureBox to render a different image in each of these pages and they don't trigger the PrintOnPage event of the PictureBox. I will add an answer with the workaround we found as soon as I can :)
PictureBox
You can use the PrintOnPage event of your PictureBox itself.
Here is example:
var source = new List<Tuple<int, string>>();
for (int index = 0; index < 100; index++)
source.Add(new Tuple<int, string>(index, "Name" + index));
var pictureBox = new XRPictureBox();
pictureBox.PrintOnPage += (sender, e) =>
{
if (_imageList[e.PageIndex] == null)
return;
pictureBox.Image = _imageList[e.PageIndex];
};
var labelItem1 = new XRLabel();
labelItem1.DataBindings.Add("Text", null, "Item1");
labelItem1.LeftF = 100;
var labelItem2 = new XRLabel();
labelItem2.DataBindings.Add("Text", null, "Item2");
labelItem2.LeftF = 200;
var detail = new DetailBand();
detail.Controls.AddRange(new XRControl[] { pictureBox, labelItem1, labelItem2 });
var report = new XtraReport();
report.Bands.Add(detail);
report.DataSource = source;
report.ShowRibbonPreview();
The result of example:
Watermarks
If you want to have only one image per page then you can use watermarks.
Here is example:
var source = new List<Tuple<int, string>>();
for (int index = 0; index < 100; index++)
source.Add(new Tuple<int, string>(index, "Name" + index));
var labelItem1 = new XRLabel();
labelItem1.DataBindings.Add("Text", null, "Item1");
labelItem1.LeftF = 100;
var labelItem2 = new XRLabel();
labelItem2.DataBindings.Add("Text", null, "Item2");
labelItem2.LeftF = 200;
var detail = new DetailBand();
detail.Controls.AddRange(new XRControl[] { labelItem1, labelItem2 });
var report = new XtraReport();
report.Bands.Add(detail);
report.DataSource = source;
report.CreateDocument();
foreach (Page page in report.Pages)
if (_imageList[page.Index] != null)
{
var watermark = new Watermark();
watermark.Image = _imageList[page.Index];
page.AssignWatermark(watermark);
}
report.ShowRibbonPreview();
Here is result: