I am creating a report through FixedDocument and I am doing it in the code behind to dynamically add data to the report.
I started using FixedDocument today and got stuck in aligning texts. It does not seem to center align. Here's my code:
using System.Windows.Documents;
....
public void GenerateReport()
{
FixedDocument document = new FixedDocument();
PageContent content = new PageContent();
FixedPage page = new FixedPage();
page.Width = document.DocumentPaginator.PageSize.Width;
page.Height = document.DocumentPaginator.PageSize.Height;
page.Background = System.Windows.Media.Brushes.AliceBlue;
//header first line
System.Windows.Controls.Canvas canvas = new System.Windows.Controls.Canvas();
canvas.Width = document.DocumentPaginator.PageSize.Width;
FixedPage.SetTop(canvas, 15);
FixedPage.SetLeft(canvas, 15);
System.Windows.Controls.TextBlock block = new System.Windows.Controls.TextBlock();
block.FontSize = 11;
block.FontWeight = FontWeights.Bold;
block.FontFamily = new System.Windows.Media.FontFamily("Tahoma");
block.Text = "This is the first line";
block.HorizontalAlignment = HorizontalAlignment.Center;
canvas.Children.Add(block);
page.Children.Add(canvas);
//header second line
System.Windows.Controls.TextBlock block2 = new System.Windows.Controls.TextBlock(); block.FontSize = 11;
block2.FontWeight = FontWeights.Bold;
block2.FontFamily = new System.Windows.Media.FontFamily("Tahoma");
block2.Text = "Daily Report";
var canvas2 = new System.Windows.Controls.Canvas();
canvas2.Children.Add(block2);
FixedPage.SetTop(canvas2, 30);
FixedPage.SetTop(canvas2, 30);
FixedPage.SetLeft(canvas2, 15);
FixedPage.SetRight(canvas2, 15);
canvas2.Width = document.DocumentPaginator.PageSize.Width;
page.Children.Add(canvas2);
((IAddChild)content).AddChild(page);
document.Pages.Add(content);
}
How will I do the alignment right?
https://learn.microsoft.com/en-us/dotnet/api/system.windows.documents.flowdocument?view=net-5.0#properties
I'm not sure if you can do this with FixedDocument. This is available in Flowdocument though with the TextAlignmentProperty.
Related
I am trying to print the contents of a rich-text box. I do that in the following way:
Obtain a TextRange from the FlowDocument.
Create a new FlowDocument with a smaller font using the TextRange.
Send this new FlowDocument to the printer.
My problem, is that the font doesn't seem to change. I would like it to go down to size 8. Instead, it remains at a fixed size. Here is my code:
private void button_Print_Click(object sender, RoutedEventArgs e)
{
IDocumentPaginatorSource ps = null;
FlowDocument fd = new FlowDocument();
PrintDialog pd = new PrintDialog();
Paragraph pg = new Paragraph();
Style style = new Style(typeof(Paragraph));
Run r = null;
string text = string.Empty;
// get the text
text = new TextRange(
this.richTextBox_Info.Document.ContentStart,
this.richTextBox_Info.Document.ContentEnd).Text;
// configure the style of the flow document
style.Setters.Add(new Setter(Block.MarginProperty, new Thickness(0)));
fd.Resources.Add(typeof(Paragraph), style);
// style the paragraph
pg.LineHeight = 0;
pg.LineStackingStrategy = LineStackingStrategy.BlockLineHeight;
pg.FontFamily = new FontFamily("Courier New");
pg.TextAlignment = TextAlignment.Left;
pg.FontSize = 8;
// create the paragraph
r = new Run(text);
r.FontFamily = new FontFamily("Courier New");
r.FontSize = 8;
pg.Inlines.Add(r);
// add the paragraph to the document
fd.Blocks.Add(pg);
ps = fd;
// format the page
fd.PagePadding = new Thickness(50);
fd.ColumnGap = 0;
fd.ColumnWidth = pd.PrintableAreaWidth;
// print the document
if (pd.ShowDialog().Value == true)
{
pd.PrintDocument(ps.DocumentPaginator, "Information Box");
}
}
I would like to add that, changing the font works just fine for the flow-document when it is inside of the rich-text box. However, when I am doing it programmatically (as shown above) I run into problems.
I try your code and found when I remove this line and then change the r.FontSize to 50, it seems work.
pg.LineHeight = 0;
I have a string containing some text (note the \n),
string mText = "Hello\nWorld";
When I apply this to a TextBlock (generated by code) like this:
TextBlock tb = new TextBlock();
tb.Foreground = (Brush)App.Current.Resources["PhoneForegroundBrush"];
tb.FontSize = (double)App.Current.Resources["PhoneFontSizeMedium"];
tb.Margin = new Thickness(24, 32, 24, 12);
tb.TextWrapping = TextWrapping.Wrap;
tb.Text = mText;
I don't see the second line. Any ideas?
[UPDATE - Added the usage of this code]
I use this in showing a PopUp on the Screen:
// Create PopUp Content:
TextBlock tb = new TextBlock();
tb.Foreground = (Brush)App.Current.Resources["PhoneForegroundBrush"];
tb.FontSize = (double)App.Current.Resources["PhoneFontSizeMedium"];
tb.Margin = new Thickness(24, 32, 24, 12);
tb.TextWrapping = TextWrapping.Wrap;
tb.Text = pMessage;
Grid grid = new Grid();
grid.Background = (Brush)App.Current.Resources["PhoneAccentBrush"];
grid.Children.Add(tb);
grid.Width = page.ActualWidth;
// Create PopUp itself:
Popup popup = new Popup();
popup.Child = grid;
// Show PopUp:
SystemTray.BackgroundColor = (Color)App.Current.Resources["PhoneAccentColor"];
popup.IsOpen = true;
You could also add the following:
tb.Text = mText + Environment.NewLine;
or
tb.Text = mText + "
" + "
"
that seems to insert the <LineBreak/> into.
I have a class that build the content for my table of contents and that works, fine and dandy.
Here's the code:
public void Build(string center,IDictionary<string,iTextSharp.text.Image> images)
{
iTextSharp.text.Image image = null;
XPathDocument rapportTekst = new XPathDocument(Application.StartupPath + #"..\..\..\RapportTemplates\RapportTekst.xml");
XPathNavigator nav = rapportTekst.CreateNavigator();
XPathNodeIterator iter;
iter = nav.Select("//dokument/brevhoved");
iter.MoveNext();
var logo = iTextSharp.text.Image.GetInstance(iter.Current.GetAttribute("url", ""));
iter = nav.Select("//dokument/gem_som");
iter.MoveNext();
string outputPath = iter.Current.GetAttribute("url", "")+center+".pdf";
iter = nav.Select("//dokument/titel");
iter.MoveNext();
this.titel = center;
Document document = new Document(PageSize.A4, 30, 30, 100, 30);
var outputStream = new FileStream(outputPath, FileMode.Create);
var pdfWriter = PdfWriter.GetInstance(document, outputStream);
pdfWriter.SetLinearPageMode();
var pageEventHandler = new PageEventHandler();
pageEventHandler.ImageHeader = logo;
pdfWriter.PageEvent = pageEventHandler;
DateTime timeOfReport = DateTime.Now.AddMonths(-1);
pageWidth = document.PageSize.Width - (document.LeftMargin + document.RightMargin);
pageHight = document.PageSize.Height - (document.TopMargin + document.BottomMargin);
document.Open();
var title = new Paragraph(titel, titleFont);
title.Alignment = Element.ALIGN_CENTER;
document.Add(title);
List<TableOfContentsEntry> _contentsTable = new List<TableOfContentsEntry>();
nav.MoveToRoot();
iter = nav.Select("//dokument/indhold/*");
Chapter chapter = null;
int chapterCount = 1;
while (iter.MoveNext())
{
_contentsTable.Add(new TableOfContentsEntry("Test", pdfWriter.CurrentPageNumber.ToString()));
XPathNodeIterator innerIter = iter.Current.SelectChildren(XPathNodeType.All);
chapter = new Chapter("test", chapterCount);
while(innerIter.MoveNext())
{
if (innerIter.Current.Name.ToString().ToLower().Equals("billede"))
{
image = images[innerIter.Current.GetAttribute("navn", "")];
image.Alignment = Image.ALIGN_CENTER;
image.ScaleToFit(pageWidth, pageHight);
chapter.Add(image);
}
if (innerIter.Current.Name.ToString().ToLower().Equals("sektion"))
{
string line = "";
var afsnit = new Paragraph();
line += (innerIter.Current.GetAttribute("id", "") + " ");
innerIter.Current.MoveToFirstChild();
line += innerIter.Current.Value;
afsnit.Add(line);
innerIter.Current.MoveToNext();
afsnit.Add(innerIter.Current.Value);
chapter.Add(afsnit);
}
}
chapterCount++;
document.Add(chapter);
}
document = CreateTableOfContents(document, pdfWriter, _contentsTable);
document.Close();
}
I'm then calling the method CreateTableOfContents(), and as such it is doing what it is supposed to do. Here's the code for the method:
public Document CreateTableOfContents(Document _doc, PdfWriter _pdfWriter, List<TableOfContentsEntry> _contentsTable)
{
_doc.NewPage();
_doc.Add(new Paragraph("Table of Contents", FontFactory.GetFont("Arial", 18, Font.BOLD)));
_doc.Add(new Chunk(Environment.NewLine));
PdfPTable _pdfContentsTable = new PdfPTable(2);
foreach (TableOfContentsEntry content in _contentsTable)
{
PdfPCell nameCell = new PdfPCell(_pdfContentsTable);
nameCell.Border = Rectangle.NO_BORDER;
nameCell.Padding = 6f;
nameCell.Phrase = new Phrase(content.Title);
_pdfContentsTable.AddCell(nameCell);
PdfPCell pageCell = new PdfPCell(_pdfContentsTable);
pageCell.Border = Rectangle.NO_BORDER;
pageCell.Padding = 6f;
pageCell.Phrase = new Phrase(content.Page);
_pdfContentsTable.AddCell(pageCell);
}
_doc.Add(_pdfContentsTable);
_doc.Add(new Chunk(Environment.NewLine));
/** Reorder pages so that TOC will will be the second page in the doc
* right after the title page**/
int toc = _pdfWriter.PageNumber - 1;
int total = _pdfWriter.ReorderPages(null);
int[] order = new int[total];
for (int i = 0; i < total; i++)
{
if (i == 0)
{
order[i] = 1;
}
else if (i == 1)
{
order[i] = toc;
}
else
{
order[i] = i;
}
}
_pdfWriter.ReorderPages(order);
return _doc;
}
The problem is however. I want to insert a page break before the table of contents, for the sake of reordering the pages, so that the table of contents is the first page, naturally. But the output of the pdf-file is not right.
Here's a picture of what it looks like:
It seems like the _doc.NewPage() in the CreateTableOfContents() method does not execute correctly. Meaning that the image and the table of contents is still on the same page when the method starts the reordering of pages.
EDIT: To clarify the above, the _doc.NewPage() gets executed, but the blank page is added after the picture and the table of contents.
I've read a couple of places that this could be because one is trying to insert a new page after an already blank page. But this is not the case.
I'll just link to the pdf files aswell, to better illustrate the problem.
The pdf with table of contents: with table of contents
The pdf without table of contents: without table of contents
Thank you in advance for your help :)
I have a line of text to display and what I want to do is underline only the heading portion of the text in the display. How do I accomplish this please?
Message: This is a message for Name of Client.
Where "Message:" is underlined.
Use RichTextBox instead !
this.myRichTextBox.SelectionStart = 0;
this.myRichTextBox.SelectionLength = this.contactsTextBox.Text.Length-1;
myRichTextBox.SelectionFont = new Font(myRichTextBox.SelectionFont, FontStyle.Underline);
this.myRichTextBox.SelectionLength = 0;
You can do that underline using the RichTextBox control
int start = rtbTextBox.Text.IndexOf("Message:", StringComparison.CurrentCultureIgnoreCase);
if(start > 0)
{
rtbTextBox.SelectionStart = start;
rtbTextBox.SelectionLength = "Message:".Length-1;
rtbTextBox.SelectionFont = new Font(rtbTextBox.SelectionFont, FontStyle.Underline);
rtbTextBox.SelectionLength = 0;
}
This example use directly the text you provided in your question. It will be better if you encapsulate this code in a private method and pass in the heading text.
For example:
private void UnderlineHeading(string heading)
{
int start = rtbTextBox.Text.IndexOf(heading, StringComparison.CurrentCultureIgnoreCase);
if(start > 0)
{
rtbTextBox.SelectionStart = start;
rtbTextBox.SelectionLength = heading.Length-1;
rtbTextBox.SelectionFont = new Font(rtbTextBox.SelectionFont, FontStyle.Underline);
rtbTextBox.SelectionLength = 0;
}
}
and call from your form whith: UnderlineHeading("Message:");
If you want to show the text using a rich text box, you could do something like this:
richTextBox1.SelectionFont = new Font("Times New Roman", 10, FontStyle.Underline);
richTextBox1.SelectedText = "Message:";
richTextBox1.SelectionFont = new Font("Times New Roman", 10, FontStyle.Regular);
richTextBox1.SelectedText = " This is a message for Name of Client.";
Or, if the message is dynamic and the header and text are always separated by a colon, you could do something like this:
string message = "Message: This is a message for Name of Client";
string[] parts = message.Split(':');
richTextBox1.SelectionFont = new Font("Times New Roman", 10, FontStyle.Underline);
richTextBox1.SelectedText = parts[0] + ":";
richTextBox1.SelectionFont = new Font("Times New Roman", 10, FontStyle.Regular);
richTextBox1.SelectedText = parts[1];
Or, if you want to show the text dynamically in labels, you could do something like this:
string message = "Message: This is a message for Name of Client";
string[] parts = message.Split(':');
Label heading = new Label();
heading.Text = parts[0] + ":";
heading.Font= new Font("Times New Roman", 10, FontStyle.Underline);
heading.AutoSize = true;
flowLayoutPanel1.Controls.Add(heading);
Label message = new Label();
message.Text = parts[1];
message.Font = new Font("Times New Roman", 10, FontStyle.Regular);
message.AutoSize = true;
flowLayoutPanel1.Controls.Add(message);
Just a thought, You can use masked text box or create a custom control with richtextbox having underline and use it in client application. I heard there is a chance of creating textbox with underline using GDI+ api but not sure.
Thanks
Mahesh kotekar
I am trying to print with WPF's PrintDialog class (namespace System.Windows.Controls in PresentationFramework.dll, v4.0.30319). This is the code that I use:
private void PrintMe()
{
var dlg = new PrintDialog();
if (dlg.ShowDialog() == true)
{
dlg.PrintVisual(new System.Windows.Shapes.Rectangle
{
Width = 100,
Height = 100,
Fill = System.Windows.Media.Brushes.Red
}, "test");
}
}
The problem is no matter what Paper Size I select for "Microsoft XPS Document Writer", the generated XPS, always, has the width and height of "Letter" paper type:
This is the XAML code I can find inside XPS package:
<FixedPage ... Width="816" Height="1056">
Changing the paper size in the print dialog only affects the PrintTicket, not the FixedPage content. The PrintVisual method produces Letter size pages, so in order to have a different page size you need to use the PrintDocument method, like so:
private void PrintMe()
{
var dlg = new PrintDialog();
FixedPage fp = new FixedPage();
fp.Height = 100;
fp.Width = 100;
fp.Children.Add(new System.Windows.Shapes.Rectangle
{
Width = 100,
Height = 100,
Fill = System.Windows.Media.Brushes.Red
});
PageContent pc = new PageContent();
pc.Child = fp;
FixedDocument fd = new FixedDocument();
fd.Pages.Add(pc);
DocumentReference dr = new DocumentReference();
dr.SetDocument(fd);
FixedDocumentSequence fds = new FixedDocumentSequence();
fds.References.Add(dr);
if (dlg.ShowDialog() == true)
{
dlg.PrintDocument(fds.DocumentPaginator, "test");
}
}