1
votes

Much like the editor you see on StackOverflow, I want users to be able to specify that parts of their text should be bold, italic, or underline, but I do not want them to be able to set the font size or family; these need to be inherited from somewhere else in the visual tree.

When placing the WPF RichTextBox control into an empty window and providing a few characters of text, the serialized representation of the rich text always includes the FontFamily. e.g., in LINQPad:

void Main()
{
    var window = new Window();
    var editor = new RichTextBox();
    window.Content = editor;
    window.ShowDialog();

    var rtf = RtfUtility.ConvertToRtf(editor.Document);
    rtf.Dump();
}

I entered "HELLO, WORLD!" into the RichTextBox.

{\rtf1\ansi\ansicpg1252\uc1\htmautsp\deff2{\fonttbl{\f0\fcharset0 Times New Roman;}{\f2\fcharset0 Segoe UI;}}{\colortbl\red0\green0\blue0;\red255\green255\blue255;}\loch\hich\dbch\pard\plain\ltrpar\itap0{\lang1033\fs18\f2\cf0 \cf0\ql{\f2 {\ltrch HELLO, WORLD!}\li0\ri0\sa0\sb0\fi0\ql\par}}}

The RTF serialization code is nothing special:

var range = new TextRange(document.ContentStart, document.ContentEnd);
using (var stream = new MemoryStream())
{
    range.Save(stream, DataFormats.Rtf);
    stream.Position = 0;
    using (var reader = new StreamReader(stream, Encoding.UTF8))
        return reader.ReadToEnd();
}

The serialized representation references both Times New Roman and Segoe UI, but this is undesirable.

Is it possible to present rich text and inherit the font family and size from elsewhere, as well as serialize it without these properties?

I suppose an alternative is to set FontFamily and FontSize to whatever I want each time the text is deserialized -- but that just seems hacky. I'd also be open to an entirely different solution that does not involve RichTextBox, if that's feasible.

2

2 Answers

0
votes

FlowDocument assumes Sergoe UI as default font. This font is in the style for FlowDocument objects.

To change this:

editor.Document.FontFamily = new FontFamily("Times New Roman");
editor.Document.FontSize = 12;

You can also create a style for all FlowDocuments using xaml declarations in App.xaml or programmatically, for each FlowDocument:

var style = new Style(typeof(FlowDocument));
style.Setters.Add(new Setter(FlowDocument.FontFamilyProperty, new FontFamily("Times New Roman")));
style.Setters.Add(new Setter(FlowDocument.FontSizeProperty, 12));
editor.Resources.Add(typeof(FlowDocument), style)

When creating style for a paragraph (new Style(typeof(Paragraph))) you can also change each individual paragraph's settings.

Unfortunately serialization saves FlowDocument's resources and all settings which are not inherited.

0
votes

You can use a textrange:

TextRange tr2 = new TextRange(mergedDocument.ContentStart, mergedDocument.ContentEnd);
        tr2.ApplyPropertyValue(Span.FontFamilyProperty, font);
        tr2.ApplyPropertyValue(Span.FontSizeProperty, "24");
        tr2.ApplyPropertyValue(List.FontFamilyProperty, font);
        tr2.ApplyPropertyValue(List.FontSizeProperty, "24");