This is a migrated thread and some comments may be shown as answers.

Adding page number in the footer

24 Answers 753 Views
RichTextBox
This is a migrated thread and some comments may be shown as answers.
Guy
Top achievements
Rank 1
Guy asked on 31 Aug 2011, 09:01 PM
Hi,

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

Sort by
0
Boby
Telerik team
answered on 06 Sep 2011, 09:41 AM
Hello Guy,
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 >>

0
Guy
Top achievements
Rank 1
answered on 06 Sep 2011, 04:28 PM
Hi Boby,

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.
0
Iva Toteva
Telerik team
answered on 07 Sep 2011, 04:35 PM
Hi Guy,

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 >>

0
Dhaval patel
Top achievements
Rank 1
answered on 19 Oct 2011, 12:03 PM
Hello,

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...
0
Iva Toteva
Telerik team
answered on 20 Oct 2011, 04:53 PM
Hello Dhaval Patel,

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 >>

0
Christian
Top achievements
Rank 1
answered on 24 Oct 2011, 08:25 AM
Hi,

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
0
Iva Toteva
Telerik team
answered on 25 Oct 2011, 05:02 PM
Hi Christian,

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 >>

0
Christian
Top achievements
Rank 1
answered on 27 Oct 2011, 11:17 AM
Is there a chance to assign a column width like * to a tabe column?
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.
0
Iva Toteva
Telerik team
answered on 01 Nov 2011, 10:32 AM
Hello Christian,

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.

Kind regards,
Iva Toteva
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

0
Allen
Top achievements
Rank 2
Iron
Veteran
answered on 01 Mar 2012, 10:20 PM
The position of the page number in this example ends up at the extreme right of the table's second row.  It is not clear how to make sure that the table in the footer is properly indented on the left and right so that its contents are also indented correctly i.e. respect left and right margins.

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.
0
Iva Toteva
Telerik team
answered on 07 Mar 2012, 12:31 PM
Hello Allen,

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
Sharpen your .NET Ninja skills! Attend Q1 webinar week and get a chance to win a license! Book your seat now >>
0
Allen
Top achievements
Rank 2
Iron
Veteran
answered on 07 Mar 2012, 03:33 PM
So I fooled around with this a bit more to resolve indenting problems, but I am not sure I did it the correct way:

<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? 
0
Iva Toteva
Telerik team
answered on 12 Mar 2012, 02:29 PM
Hello Allen,
 
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
Sharpen your .NET Ninja skills! Attend Q1 webinar week and get a chance to win a license! Book your seat now >>
0
Roberto Pantalena
Top achievements
Rank 1
answered on 24 May 2012, 11:02 AM
Hi, you can easily manage the footer using this code:

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
0
Tayyab
Top achievements
Rank 1
answered on 05 Jul 2012, 08:56 PM
I tried this but I got error on new PageField(). which is Object reference not set to an instance of an object.

I want to add pagenumber on footer

Thanks
0
Boby
Telerik team
answered on 10 Jul 2012, 03:55 PM
Hello Tayyab,
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 >>

0
YYZRichard
Top achievements
Rank 2
answered on 23 Jul 2012, 02:41 PM
I'm having the same issue "Object reference not set to an instance of an object".
Any way you could attach a project example on how to use the PageField() programmatically.
Thank you.

0
Tayyab
Top achievements
Rank 1
answered on 24 Jul 2012, 05:39 PM
can't we do paging in header and footer  like
page 1 of 3
page 2 of 3 
page 3 of 3 


Thanks
0
Iva Toteva
Telerik team
answered on 26 Jul 2012, 01:32 PM
Hi,

@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.

0
HTC
Top achievements
Rank 1
answered on 04 Jun 2013, 12:38 PM
Hi Telerik,

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.
0
Roberto Pantalena
Top achievements
Rank 1
answered on 06 Jun 2013, 07:50 AM
Hello "HTC", i think you can manage this by using the FieldRangeStart, and setting its SkipPositionBefore property.
Hope this helps,
Roberto
0
HTC
Top achievements
Rank 1
answered on 06 Jun 2013, 08:50 AM
Hello Roberto Pantalena, I try to set the SkipPositionBefore property. But it is readonly. Could you give me some sample code? Thank you very much.

0
Roberto Pantalena
Top achievements
Rank 1
answered on 06 Jun 2013, 09:13 AM
You can achieve the behavior you are looking for by creating several sections in your document - cover page, table of contents, ecc.
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;
Now when you insert a page field in the second section, it will start from 1.

This is an explanation that I found in another Telerik forum, hope Helps
Roberto
0
Petya
Telerik team
answered on 07 Jun 2013, 08:19 AM
Hello,

@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.

Tags
RichTextBox
Asked by
Guy
Top achievements
Rank 1
Answers by
Boby
Telerik team
Guy
Top achievements
Rank 1
Iva Toteva
Telerik team
Dhaval patel
Top achievements
Rank 1
Christian
Top achievements
Rank 1
Allen
Top achievements
Rank 2
Iron
Veteran
Roberto Pantalena
Top achievements
Rank 1
Tayyab
Top achievements
Rank 1
YYZRichard
Top achievements
Rank 2
HTC
Top achievements
Rank 1
Petya
Telerik team
Share this question
or