Example T531470
Visible to All Users

Rich Text Editor for WinForms - How to Enable Line Numbering and Count Document Rows

This example enables line numbering for the first document section. Line numbering starts at number one and restarts at the new section. Numbers are displayed on each second line and are indented from the text at a distance equal to 75 documents (0.25 of an inch).

The Custom Draw technique is used to display the line number column with a color background.

image

Implementation Details

The Section.LineNumbering property enables line numbering for the first document section.

Set the AllowDisplayLineNumbers property to true in the SimpleView and DraftView views to display line numbering. To make line numbers visible, the left padding is increased to 60 points.

The Line Number document style defines the used font and color.

Create a custom PagePainter descendant which implements the methods required to draw the column background and the line numbers. Handle the RichEditControl.BeforePagePaint event and set the BeforePagePaintEventArgs.Painter property to the PagePainter descendant instance.

Create an instance of the LayoutVisitor descendant and let it traverse the page layout. When it encounters a new row, it calls the VisitRow method. This method increments the row counter to count the lines on a page. To run the visitor each time after building the document layout, handle the DocumentLayout.DocumentFormatted event.

Files to Review

Documentation

Does this example address your development requirements/objectives?

(you will be redirected to DevExpress.com to submit your response)

Example Code

LineNumberingExample/Form1.cs(vb)
C#
//using DevExpress.XtraRichEdit.API.Layout; //using DevExpress.XtraRichEdit.API.Native; using DevExpress.Portable; using DevExpress.XtraRichEdit; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace LineNumberingExample { public partial class Form1 : Form { public Form1() { InitializeComponent(); ribbonControl1.SelectedPage = exampleRibbonPage1; richEditControl1.DocumentLoaded += RichEditControl1_DocumentLoaded; richEditControl1.DocumentLayout.DocumentFormatted += DocumentLayout_DocumentFormatted; } private void Form1_Load(object sender, EventArgs e) { richEditControl1.LoadDocument("Grimm.docx"); } private void RichEditControl1_DocumentLoaded(object sender, EventArgs e) { richEditControl1.ActiveViewType = DevExpress.XtraRichEdit.RichEditViewType.Simple; #region #linenumbering this.richEditControl1.Views.SimpleView.Padding = new PortablePadding(60, 4, 4, 0); this.richEditControl1.Views.DraftView.Padding = new PortablePadding(60, 4, 4, 0); richEditControl1.Views.SimpleView.AllowDisplayLineNumbers = true; richEditControl1.Views.DraftView.AllowDisplayLineNumbers = true; richEditControl1.Document.Sections[0].LineNumbering.Start = 1; richEditControl1.Document.Sections[0].LineNumbering.CountBy = 2; richEditControl1.Document.Sections[0].LineNumbering.Distance = 75f; richEditControl1.Document.Sections[0].LineNumbering.RestartType = DevExpress.XtraRichEdit.API.Native.LineNumberingRestart.Continuous; richEditControl1.Document.CharacterStyles["Line Number"].FontName = "Courier"; richEditControl1.Document.CharacterStyles["Line Number"].FontSize = 10; richEditControl1.Document.CharacterStyles["Line Number"].ForeColor = Color.DarkGray; richEditControl1.Document.CharacterStyles["Line Number"].Bold = true; #endregion #linenumbering } #region #BeforePagePaint private void RichEditControl1_BeforePagePaint(object sender, DevExpress.XtraRichEdit.BeforePagePaintEventArgs e) { if (e.CanvasOwnerType == DevExpress.XtraRichEdit.API.Layout.CanvasOwnerType.Printer) { return; } DevExpress.XtraRichEdit.API.Native.CharacterStyle style = richEditControl1.Document.CharacterStyles["Line Number"]; MyPagePainter customPagePainter = new MyPagePainter(richEditControl1, SystemColors.Info, style); customPagePainter.LineNumberPadding = 60; e.Painter = customPagePainter; } #endregion #BeforePagePaint private void barCheckLineNumberBackColoring_CheckedChanged(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { if (barCheckLineNumberBackColoring.Checked) richEditControl1.BeforePagePaint += RichEditControl1_BeforePagePaint; else richEditControl1.BeforePagePaint -= RichEditControl1_BeforePagePaint; richEditControl1.Refresh(); } #region #DocumentFormatted private void DocumentLayout_DocumentFormatted(object sender, EventArgs e) { this.BeginInvoke((MethodInvoker)(() => { if (this.Visible) { MyLayoutVisitor visitor = new MyLayoutVisitor(richEditControl1.Document); int pageCount = richEditControl1.DocumentLayout.GetFormattedPageCount(); for (int i = 0; i < pageCount; i++) { visitor.Visit(richEditControl1.DocumentLayout.GetPage(i)); } resultBarStaticItem.Caption = String.Format("Document has {0} lines", visitor.RowIndex); } })); } #endregion #DocumentFormatted } }
LineNumberingExample/MyLayoutVisitor.cs(vb)
C#
using DevExpress.XtraRichEdit.API.Layout; using DevExpress.XtraRichEdit.API.Native; using System; namespace LineNumberingExample { #region #MyLayoutVisitor public class MyLayoutVisitor : LayoutVisitor { Document document; public int RowIndex { get; private set; } public MyLayoutVisitor(Document doc) { this.document = doc; RowIndex = 0; } protected override void VisitRow(LayoutRow row) { RowIndex++; base.VisitRow(row); } } #endregion #MyLayoutVisitor }
LineNumberingExample/MyPagePainter.cs(vb)
C#
using DevExpress.XtraRichEdit; using DevExpress.XtraRichEdit.API.Layout; using DevExpress.XtraRichEdit.API.Native; using System.Drawing; namespace LineNumberingExample { #region #MyPagePainter public class MyPagePainter : PagePainter { RichEditControl richEditControl; int previousColumnIndex = -1; Font lineNumberFont; public MyPagePainter(RichEditControl richEdit) : base() { richEditControl = richEdit; } public MyPagePainter(RichEditControl richEdit, Color backColor, CharacterStyle style) : base() { richEditControl = richEdit; NumberingHighlightColor = backColor; NumberingFontName = style.FontName; NumberingFontSize = style.FontSize ?? 10F; NumberingFontColor = style.ForeColor ?? Color.Black; } public string NumberingFontName { get; set; } public float NumberingFontSize { get; set; } public Color NumberingFontColor { get; set; } public Color NumberingHighlightColor { get; set; } public int LineNumberPadding { get; set; } public override void DrawPage(LayoutPage page) { lineNumberFont = new Font(NumberingFontName, NumberingFontSize, FontStyle.Regular); base.DrawPage(page); lineNumberFont.Dispose(); } public override void DrawPageArea(LayoutPageArea pageArea) { Rectangle lineNumberBounds = new Rectangle(new Point(-LineNumberPadding, 0), new Size(LineNumberPadding, pageArea.Bounds.Height)); Canvas.FillRectangle(new RichEditBrush(NumberingHighlightColor), lineNumberBounds); base.DrawPageArea(pageArea); previousColumnIndex = -1; } public override void DrawColumn(LayoutColumn column) { LayoutPageArea pageArea = column.GetParentByType<LayoutPageArea>(); if (pageArea != null) { int leftBoundary = 0; if (previousColumnIndex >= 0) { leftBoundary = pageArea.Columns[previousColumnIndex].Bounds.Right; } if (column.LineNumbers.Count > 0) { HighlightLineNumberingArea(column, leftBoundary); } previousColumnIndex++; } base.DrawColumn(column); } public override void DrawLineNumberBox(LineNumberBox lineNumberBox) { Canvas.DrawString(lineNumberBox.Text, lineNumberFont, new RichEditBrush(NumberingFontColor), lineNumberBox.Bounds, this.richEditControl.LayoutUnit); } void HighlightLineNumberingArea(LayoutColumn column, int leftBoundary) { LayoutPage page = column.GetParentByType<LayoutPage>(); Rectangle marginBounds = new Rectangle(new Point(leftBoundary, 0), new Size(column.Bounds.X - leftBoundary, page.Bounds.Height)); Canvas.FillRectangle(new RichEditBrush(NumberingHighlightColor), marginBounds); } } #endregion #MyPagePainter }

Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.