Skip to content
Dustin Horne edited this page Mar 5, 2026 · 1 revision

IO — Import and Export

Namespace: ParentElement.RichText.Core.IO

Built-in RTF import and export, plus base classes for implementing custom importers and exporters.


RtfExporter

Serializes a document to Rich Text Format (RTF). Extends ExporterBase and implements IExportContent.

public class RtfExporter : ExporterBase

Methods

Method Returns Description
ExportAsync(IDocumentController, Stream) Task Export the document to an output stream
ExportAsync(IDocumentController, string) Task Export the document to a file path
ToRtfString(IReadOnlyList<ContentBlock>, IStyle?) string Static helper — convert a content block list directly to an RTF string without a controller

Supported Features

  • Bold, italic, underline, strikethrough, subscript, superscript
  • Font family, font size, font color, and background highlight color
  • Paragraph alignment (left, center, right, justified)
  • Paragraph indentation and first-line indent
  • Bullet and numbered lists with nesting levels
  • Line spacing
  • Inline images (embedded as \pict\pngblip)
  • Embedded tables with cell spanning, borders, and header rows

Usage

IExportContent exporter = new RtfExporter();

// To a file
await exporter.ExportAsync(editor, @"C:\Documents\report.rtf");

// To a stream (e.g. clipboard)
using var ms = new MemoryStream();
await exporter.ExportAsync(editor, ms);
string rtf = Encoding.ASCII.GetString(ms.ToArray());

// From a content model (no controller required)
var reader  = editor.GetContentReader();
var blocks  = reader.GetContent().ToList();
string rtf  = RtfExporter.ToRtfString(blocks, reader.Document.DefaultStyle);

RtfImporter

Parses Rich Text Format (RTF) and loads it into a document. Extends ImporterBase and implements IImportContent.

public class RtfImporter : ImporterBase

Methods

Method Returns Description
ImportAsync(IDocumentController, Stream) Task Import from an RTF stream
ImportAsync(IDocumentController, string) Task Import from an RTF file path

Supported Features

  • Font table and color table parsing
  • Bold, italic, underline, strikethrough
  • Font size and color
  • Paragraph alignment
  • Bullet and numbered lists
  • Paragraph indentation
  • Embedded PNG images (\pict\pngblip)
  • Nested tables with row/column spanning

Usage

IImportContent importer = new RtfImporter();

// From a file
await importer.ImportAsync(editor, @"C:\Documents\report.rtf");

// From a stream
using var fs = File.OpenRead("report.rtf");
await importer.ImportAsync(editor, fs);

ExporterBase

Abstract base class for all exporters. Implements IExportContent by declaring both ExportAsync overloads as abstract.

public abstract class ExporterBase : IExportContent

Abstract Methods

Method Returns Description
ExportAsync(IDocumentController, Stream) Task Export to a stream — must be overridden
ExportAsync(IDocumentController, string) Task Export to a file path — must be overridden

Implementing a Custom Exporter

public class MarkdownExporter : ExporterBase
{
    public override async Task ExportAsync(IDocumentController controller, Stream outputStream)
    {
        var reader = controller.GetContentReader();
        var sb = new StringBuilder();

        foreach (var block in reader.GetContent())
        {
            foreach (var run in block.Runs)
            {
                if (!run.IsImage && !run.IsTable)
                    sb.Append(run.Text);
            }
            sb.AppendLine();
        }

        var bytes = Encoding.UTF8.GetBytes(sb.ToString());
        await outputStream.WriteAsync(bytes);
    }

    public override async Task ExportAsync(IDocumentController controller, string filePath)
    {
        using var fs = File.Create(filePath);
        await ExportAsync(controller, fs);
    }
}

ImporterBase

Abstract base class for all importers. Implements IImportContent and provides protected helpers for inserting parsed paragraphs and tables into a DocumentController.

public abstract class ImporterBase : IImportContent

Abstract Methods

Method Returns Description
ImportAsync(IDocumentController, Stream) Task Import from a stream — must be overridden
ImportAsync(IDocumentController, string) Task Import from a file path — must be overridden

Protected Helpers

Method Returns Description
InsertParsedContent(IDocumentController, IEnumerable<ParsedParagraph>) Task Insert a flat sequence of paragraphs into the document
InsertMixedBlocks(IDocumentController, List<object>) Task Insert a mixed sequence of ParsedParagraph and ParsedTable objects
InsertParsedTable(IDocumentController, ParsedTable) void (static) Create and populate an inline table from a ParsedTable model
WriteCellContent(ICellWriter, List<ParsedParagraph>) void (static) Write a parsed paragraph list into a cell via ICellWriter

Intermediate Models

These protected record / class types are shared by RtfImporter and any custom importers:

ParsedRun

Member Type Description
Text string Plain text content
Style Style Character style
ImageData byte[]? PNG bytes for image runs
ImageWidth float Display width in pixels
ImageHeight float Display height in pixels

ParsedParagraph

Member Type Default Description
Alignment TextAlignment — Paragraph alignment
Runs List<ParsedRun> — Inline runs
BlockIndent float 0 Left block indent
ListType ListType None List marker type
ListLevel int 0 List nesting depth
LineSpacing float? null Line height multiplier

ParsedTable

Member Type Description
Rows int Row count
Cols int Column count
Cells ParsedTableCell?[][] Row-major grid; null = spanned slot
BorderStyle TableBorderStyle Border style
BorderWidth float Border thickness
BorderColor SKColor Border color
IncludeHeader bool Whether row 0 is a header row
ColWidths float[]? Explicit column widths, or null for auto-distribute

ParsedTableCell

Member Type Description
IsHeader bool Header cell flag
RowSpan int Row span (mutable for two-pass parsing)
ColSpan int Column span (mutable for two-pass parsing)
Content List<ParsedParagraph> Cell content paragraphs
CellBackgroundColor SKColor? Cell-level background color

Implementing a Custom Importer

public class PlainTextImporter : ImporterBase
{
    public override async Task ImportAsync(IDocumentController controller, Stream inputStream)
    {
        using var reader = new StreamReader(inputStream);
        var text = await reader.ReadToEndAsync();
        var paragraphs = text
            .Split('\n')
            .Select(line => new ParsedParagraph(
                Alignment: TextAlignment.Left,
                Runs: new List<ParsedRun> { new ParsedRun(line, new Style()) }))
            .ToList();

        await InsertParsedContent(controller, paragraphs);
    }

    public override async Task ImportAsync(IDocumentController controller, string filePath)
    {
        using var fs = File.OpenRead(filePath);
        await ImportAsync(controller, fs);
    }
}

See also: IExportContent · IImportContent · Content-Model · ICellWriter

Clone this wiki locally