I Have a problem of adding a customized page number in the RadDocument i need to export in Pdf Format. I Create dynamically a Footer in which I added current the page number. The problem i m facing is the shown footer is always the first i created (i have always Page 1 as number of each page).
Here is my method i use to set the header/ footer of each section
private void SetHeaderFooter(Section section, Header header, Footer footer)
{
if (header != null)
{
section.Headers.Default = header;
section.HeaderTopMargin = 5;
}
if (footer != null)
{
section.Footers.Default = footer;
section.FooterBottomMargin = 2;
}
}
I make sure each time i set the footer to each section to have in the footer the right page number. But in the whole document i have "Page 1" as page number means only the first footer created is taken into account...
Any thing i miss???
Thanks for your help.
Best Regards
24 Answers, 1 is accepted
Currently RadDocument model supports only one section per document; we will try to address this issue in the following official release (Q3 2011). You can, however, add page numbers to the headers and footers by adding a PageField:
this
.radRichTextBox.Document.Sections.First.Footers.Default.Body.InsertField(
new
PageField());
Don't hesitate to contact us if you have other questions.
Kind regards,Boby
the Telerik team
Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's DevProConnections Awards. We are competing in mind-blowing 20 categories and every vote counts! VOTE for Telerik NOW >>
Thank you for your quick reply. I tried the code you suggested me, but the only think i have in the footer is "{ PAGE }" but no page number.. Any think i missed??
Thank you for your Help.
Fields have different display modes and this is how the PageField is shown in FieldDisplayMode.Code.
You can use the overload method for inserting fields using their ResultFragment like this:
this
.radRichTextBox.Document.Sections.First.Footers.Default.Body.InsertField(
new
PageField(), FieldDisplayMode.Result);
You can toggle between the different modes of a field from code-behind like this:
this
.radRichTextBox.ChangeAllFieldsDisplayMode(FieldDisplayMode.Result);
or using the context menu: Right-Click on a Field -> Toggle Field Codes. Greetings,
Iva
the Telerik team
Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's DevProConnections Awards. We are competing in mind-blowing 20 categories and every vote counts! VOTE for Telerik NOW >>
1. Is it possible to give style to page number?
2. Is it possible to give page number at bottom right?
3. Is it possible to give page number like
Page 1 of 10
Page 2 of 10
Thanks in advance...
1. Currently, it is not possible to change the style of a page field programmatically. This can only be done using the UI. However, the changes in the style such as fore color, font size, etc. are only persisted when the document is exported to PDF. With the other formats, the formatting is lost. We will be reviewing this limitation, most probably for the official Q3 release.
2. You can insert a PageField in the footer ina paragraph, which is aligned right in the following way:
private
Footer GetFooterDocument()
{
Footer footer =
new
Footer();
RadDocument document =
new
RadDocument();
Section section =
new
Section();
Paragraph paragraph =
new
Paragraph();
paragraph.TextAlignment = RadTextAlignment.Right;
section.Blocks.Add(paragraph);
document.Sections.Add(section);
document.MeasureAndArrangeInDefaultSize();
document.InsertField(
new
PageField());
footer.Body = document;
return
footer;
}
Then, you can update the footer to this Footer instance in the following way:
this
.editor.UpdateFooter(
this
.editor.Document.Sections.First, HeaderFooterType.Default,
this
.GetFooterDocument());
3. It is possible to create page fields that have a result string like the one in your post, but they can only be used in the main document, i.e. they cannot be embedded in the headers and footers. You can see how custom fields can be implemented in Boby's post here. The pagesNumber retrieved in the GetResultFragment() method is the number of pages in the document. Overall you can achieve the format you have quoted like this:
protected
override
DocumentFragment GetResultFragment()
{
int
pageNumber = 0;
int
pagesCount = 0;
if
(
this
.Document !=
null
)
{
DocumentPosition position =
new
DocumentPosition(
this
.Document);
position.MoveToStartOfDocumentElement(
this
.FieldStart);
SectionLayoutBox sectionBox = position.GetCurrentSectionBox();
pageNumber = sectionBox.PageNumber;
pagesCount = DocumentStructureCollection.GetChildrenCount(
this
.Document.DocumentLayoutBox);
}
string
resultString =
"Page "
+ pageNumber +
" of "
+ pagesCount;
return
base
.CreateFragmentFromText(resultString);
}
I hope this answers your questions.
Regards,
Iva Toteva
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
is it possible to have a left aligned Text in the footer and a right aligned text + pagenumber on the right side?
I cant figure out how to to this.
Best Regards
The easiest way to achieve this layout is using a table with two rows.
A table with two rows containing a PageField in the second row can be created programmatically like this:
public
RadDocument CreateDocumentProgrammatically()
{
RadDocument document =
new
RadDocument();
Section section =
new
Section();
Paragraph emptyParagraph =
new
Paragraph();
section.Blocks.Add(emptyParagraph);
Table table =
new
Table();
TableRow row1 =
new
TableRow();
TableCell cell11 =
new
TableCell();
cell11.Blocks.Add(
this
.GetParagraphWithText(
"Text aligned left"
));
TableCell cell12 =
new
TableCell();
cell12.Blocks.Add(
this
.GetParagraphWithText(
"Text aligned right"
));
cell12.Blocks.Add(
new
Paragraph());
cell12.TextAlignment = RadTextAlignment.Right;
row1.Cells.Add(cell11);
row1.Cells.Add(cell12);
table.Rows.Add(row1);
table.Borders =
new
TableBorders(
new
Telerik.Windows.Documents.Model.Border(BorderStyle.None));
section.Blocks.Add(table);
Paragraph emptyParagraph2 =
new
Paragraph();
section.Blocks.Add(emptyParagraph2);
document.Sections.Add(section);
document.MeasureAndArrangeInDefaultSize();
document.CaretPosition.MoveToInline(cell12.EnumerateChildrenOfType<Inline>().Last().GetAssociatedLayoutBoxes().Last()
as
InlineLayoutBox, 0);
document.InsertField(
new
PageField());
document.UpdateAllFields(FieldDisplayMode.Result);
return
document;
}
You can set this document to be used as a footer like this:
this
.editor.Document.Sections.First.Footers.Default =
new
Footer() { Body =
this
.CreateDocumentProgrammatically() };
More information on the document elements hierarchy can be found in our online documentation.
Note that you have to add the page fields last, because they require that the document they are inserted in has been measured, whereas creating a document by manipulating the Blocks collection of Section and the Inlines collection of Paragraph require that the document has not been measured before. Kind regards,
Iva Toteva
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
With the suggested approach, the columns have equal width, but the content of column 0 needs more than half the page, so its printed in two rows.
You can also set the preferred width of a cell in the following way:
cell11.PreferredWidth =
new
TableWidthUnit(620);
The table width unit is pixels, so this will make the cell have a width of 620 px.
Another thing you may want to customize is the layout mode of the table. By default, it is "Auto", which means that the width of the column is determined by the size of the largest word in a cell. You can set it to "Fixed" like this:
table.LayoutMode = TableLayoutMode.Fixed;
I hope this helps.
Iva Toteva
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
In fact, the left and right margin setting seems very very mysterious at best. Is there a modification of this example which can create a footer that respects the margins of the main document automatically and sizes the table accordingly? Or failing that, a clear example of how to set the margins for the footer table? Thanks.
The method CreateDocumentProgrammatically creates a Table with Auto width, which is sized according to the available space on the page. I tested how it works for documents with different page margins and the page number appeared just where it should be - on the very right in the editable part of the document.
We would appreciate some more details on the setup you want to achieve (in the form of a docx document, screenshots, etc) in order to be able to advise you further how to create such a document.
All the best,
Iva Toteva
the Telerik team
<
Rtf:RtfDataProvider
x:Name
=
"rtfDataProvider"
Rtf
=
"{Binding SysMessageText, Converter= {StaticResource _txtToRtfConverter}}"
RichTextBox
=
"{Binding ElementName=radRichTextBox}"
SetupDocument
=
"RtfDataProviderSetupDocument"
/>
<
telerik:RadRichTextBox
x:Name
=
"radRichTextBox"
LayoutMode
=
"Paged"
Grid.Row
=
"1"
FontFamily
=
"Segoe UI"
FontSize
=
"10"
FontStyle
=
"Normal"
FontWeight
=
"Normal"
DocumentInheritsDefaultStyleSettings
=
"True"
BorderThickness
=
"2,2,2,2"
IsReadOnly
=
"True"
HorizontalAlignment
=
"Left"
VerticalAlignment
=
"Top"
IsSpellCheckingEnabled
=
"False"
IsContextMenuEnabled
=
"True"
IsSelectionMiniToolBarEnabled
=
"False"
ScrollViewer.HorizontalScrollBarVisibility
=
"Auto"
ScrollViewer.VerticalScrollBarVisibility
=
"Auto"
>
<
telerik:RadDocument
x:Name
=
"PART_Document"
LayoutMode
=
"Paged"
DefaultPageLayoutSettings
=
"793,1123"
/>
</
telerik:RadRichTextBox
>
and the relevant bits of the following converter to turn a text string into Rtf
public
object
Convert(
object
value, Type targetType,
object
parameter, CultureInfo culture)
{
var myRichTextBox =
new
RadRichTextBox();
var style =
new
StyleDefinition();
style.CopyPropertiesFrom(myRichTextBox.CurrentEditingStyle);
RadDocument headerDoc =
new
RadDocument();
RadDocument footerDoc =
new
RadDocument();
//header
Section hSection =
new
Section();
headerDoc.Sections.Add(hSection);
headerDoc.SectionDefaultPageMargin =
new
Padding(95, 95, 95, 95);
Paragraph hparagraph =
new
Paragraph();
hparagraph.LineSpacing = 1;
hparagraph.TextAlignment = RadTextAlignment.Center;
hparagraph.LeftIndent = 0;
hSection.Blocks.Add(hparagraph);
var hspan =
new
Span() { FontSize = 14, FontWeight = FontWeights.Bold };
hspan.Text = String.Format(
"System Messages - document generated at: {0}"
, DateTime.Now.ToString(
"F"
));
hparagraph.Inlines.Add(hspan);
// footer
Header header =
new
Header();
header.Body = headerDoc;
Footer footer =
new
Footer() { Body =
this
.CreateFooterDocument() };
//footer.Body.InsertField(new PageField());
Section section =
new
Section();
section.PageMargin =
new
Padding(95, 95, 95, 95);
section.Headers.Default = header;
section.Footers.Default = footer;
//section.Style = style;
var paragraph =
new
Paragraph();
paragraph.LineSpacing = 1;
paragraph.TextAlignment = RadTextAlignment.Left;
paragraph.LeftIndent = 0;
var span =
new
Span();
span.Text =
" "
;
span.FontSize = 9;
span.FontWeight = FontWeights.Normal;
paragraph.Inlines.Add(span);
section.Blocks.Add(paragraph);
/*
* must add span to the paragraph - insertinline to the document puts it all in as a single blob paragraph
*
*/
var lines = ((
string
)value).Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
foreach
(var line
in
lines)
{
paragraph =
new
Paragraph();
paragraph.LineSpacing = 1;
paragraph.TextAlignment = RadTextAlignment.Left;
paragraph.LeftIndent = 0;
span =
new
Span() { FontSize = 9, FontWeight = FontWeights.Normal };
var s = String.Format(
"{0}"
, line.Replace(Environment.NewLine, String.Empty).Trim());
if
(!String.IsNullOrEmpty(s))
{
span.Text = s;
paragraph.Inlines.Add(span);
section.Blocks.Add(paragraph);
}
}
myRichTextBox.Document.Sections.Add(section);
return
new
RtfFormatProvider().Export(myRichTextBox.Document);
}
and this window constructor and FormatDocument() void method
// CODE-BEHIND
private
void
RtfDataProviderSetupDocument(
object
sender, SetupDocumentEventArgs e)
{
FormatDocument();
#if DEBUG
var xStats = e.Document.GetStatisticsInfo();
Debug.Print(
"Chars {0}"
, xStats.CharactersCount);
Debug.Print(
"Lines {0}"
, xStats.LinesCount);
#endif
}
Here is FormatDocument() which does the document massaging I found I needed.
private
void
FormatDocument()
{
this
.radRichTextBox.Document.LayoutMode = DocumentLayoutMode.Paged;
this
.radRichTextBox.Document.LineSpacing = 1;
this
.radRichTextBox.Document.ParagraphDefaultSpacingAfter = 0;
this
.radRichTextBox.Document.SectionDefaultPageMargin =
new
Padding(125, 100, 100, 100);
this
.radRichTextBox.Document.UpdateLayout();
this
.radRichTextBox.Document.UpdateAllFields(FieldDisplayMode.Result);
this
.radRichTextBox.Document.MeasureAndArrangeInDefaultSize();
#if DEBUG
var x =
this
.radRichTextBox.Document.DefaultPageLayoutSettings;
var y =
this
.radRichTextBox.Document.LineSpacing;
var z =
this
.radRichTextBox.Document.ParagraphDefaultSpacingAfter;
var a =
this
.radRichTextBox.Document.ParagraphDefaultSpacingBefore;
var mr =
this
.radRichTextBox.Document.SectionDefaultPageMargin;
foreach
(Section sec
in
this
.radRichTextBox.Document.Sections)
{
var secMargin = sec.ActualPageMargin;
var secFooterMargin = sec.FooterBottomMargin;
var secHeaderMargin = sec.HeaderTopMargin;
var lm = sec.PageMargin.Left;
var rm = sec.PageMargin.Right;
var bm = sec.PageMargin.Size;
}
#endif
}
The iteration over all the sections of the document seems really klutzy but I had to do it to get the document to present properly and print.
Was there some way in code-behind that I could have told the RadDocument what to use for L/R/Top/Bottm margin and
so on by default?
I am afraid I may not be getting the goal you are trying to achieve, because as previously mentioned, the CreateDocumentProgrammatically method positions the PageField in what I gather is the place you would like it to appear.
When it comes to your code, we would appreciate it if you could open a support ticket and attach a working project that illustrates the incorrect behavior. The reason for this request is that the code for CreateFooterDocument is missing and the insertion of the page field has been commented out. In this way, we cannot investigate what behavior you are trying to adjust and if you have managed to do so.
Some other things that are not quite clear about your implementation are:
1. Why are you using RtfDataProvider to bind the content of the document when your text seems to be plain text (judging from the code in the converter)?
2. The way you use SetupDocument event - this event offers the document to-be-shown in the rich text box, so that you can do some final customization. In order to do so, you should use the document that is passed as a parameter to the event args (e.Document) and not radRichTextBox.Document;
3. How are you using the variables from the snippet below to adjust the printing:
var x =
this
.radRichTextBox.Document.DefaultPageLayoutSettings;
var y =
this
.radRichTextBox.Document.LineSpacing;
var z =
this
.radRichTextBox.Document.ParagraphDefaultSpacingAfter;
var a =
this
.radRichTextBox.Document.ParagraphDefaultSpacingBefore;
var mr =
this
.radRichTextBox.Document.SectionDefaultPageMargin;
foreach
(Section sec
in
this
.radRichTextBox.Document.Sections)
{
var secMargin = sec.ActualPageMargin;
var secFooterMargin = sec.FooterBottomMargin;
var secHeaderMargin = sec.HeaderTopMargin;
var lm = sec.PageMargin.Left;
var rm = sec.PageMargin.Right;
var bm = sec.PageMargin.Size;
Looking forward to your reply.
All the best,
Iva Toteva
the Telerik team
rtb.Document.Sections.First.Footers.Default.Body = new RadDocument();
rtb.Document.Sections.First.Footers.Default.Body.Insert("Page ", new Telerik.Windows.Documents.Model.Styles.StyleDefinition());
rtb.Document.Sections.First.Footers.Default.Body.InsertField(new PageField(), FieldDisplayMode.Result);
in this case, the footer contains "Page 1", "Page 2" etc...
Greetings,
Roberto
I want to add pagenumber on footer
Thanks
You should provide type for the style definition:
RadDocument defaultFooterBody =
new
RadDocument();
defaultFooterBody.Insert(
"Page "
,
new
StyleDefinition(StyleType.Default));
defaultFooterBody.InsertField(
new
PageField(), FieldDisplayMode.Result);
// you can use this line if the main document isn't shown in the RadRichTextBox already (i.e. it is not measured)
// it will ensure the document have valid structure
//this.radRichTextBox.Document.EnsureDocumentMeasuredAndArranged();
this
.radRichTextBox.Document.Sections.First.Footers.Default.Body = defaultFooterBody;
All the best,
Boby
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
Any way you could attach a project example on how to use the PageField() programmatically.
Thank you.
page 1 of 3
page 2 of 3
page 3 of 3
Thanks
@Richard:
Could you please elaborate a bit more on your implementation or even open a support ticket and attach a project, so that we can see what is wrong in your application?
@Tayyab:
There is no page field that will be evaluated as "page x of y"; however you can insert a PageField, text " of " and a NumPagesField. Here is an example how such a document can be created and used for the header of a document:
void
radRichTextBox_Loaded(
object
sender, RoutedEventArgs e)
{
this
.radRichTextBox.Document.Sections.First.Headers.Default.Body =
this
.CreateDocumentWithPageField();
}
private
RadDocument CreateDocumentWithPageField()
{
RadDocument document =
new
RadDocument();
Section section =
new
Section();
Paragraph paragraph =
new
Paragraph();
PageField pageField =
new
PageField() { DisplayMode = FieldDisplayMode.Result };
FieldRangeStart pageFieldStart =
new
FieldRangeStart();
pageFieldStart.Field = pageField;
FieldRangeEnd pageFieldEnd =
new
FieldRangeEnd();
pageFieldEnd.Start = pageFieldStart;
paragraph.Inlines.Add(pageFieldStart);
paragraph.Inlines.Add(pageFieldEnd);
FieldRangeStart numPagesFieldStart =
new
FieldRangeStart();
numPagesFieldStart.Field =
new
NumPagesField() { DisplayMode = FieldDisplayMode.Result };
FieldRangeEnd numPagesFieldEnd =
new
FieldRangeEnd();
numPagesFieldEnd.Start = numPagesFieldStart;
paragraph.Inlines.Add(
new
Span(
" of "
));
paragraph.Inlines.Add(numPagesFieldStart);
paragraph.Inlines.Add(numPagesFieldEnd);
section.Blocks.Add(paragraph);
document.Sections.Add(section);
return
document;
}
Kind regards,
Iva Toteva
the Telerik team
Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.
I try the following way and it works well.
1 of 3
2 of 3
3 of 3
But the first page is cover page, I just want :
1 of 2
2 of 2
Could you tell me how to do?
Thanks.
Hope this helps,
Roberto
Then make sure the sections you want paged have theirs FirstPageNumber property set.
For example, you can create two sections: put the intro information in the first one, and the content in the second section. Then you should set the mentioned property as follows:
secondSection.FirstPageNumber = 1;
This is an explanation that I found in another Telerik forum, hope Helps
Roberto
@Robertom, thank you for helping out in the public forums, what you said in your last post is indeed the way to skip pages when adding page number.
Additionally, note that when inserting content in header/footer you have to unlink the header/footer from the one of the previous section, so that the added content will not be visible in those pages too.
Do not hesitate to contact us if you have other questions.
Regards,
Petya
Telerik
Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.