2
votes

I am trying to get and set rich text in a ;RichEditBox, but every time I do perform a GetText then a SetText, one extra carriage return is added. Here the super simple example with a button that does get then set. Try it out to see one extra carriage return being added every time you perform the Get-Set.

XAML

<StackPanel>
    <Button Content="Get-Set" Click="OnGetSet"/>
    <RichEditBox x:Name="RichEditor" Width="300" Height="200"/>
</StackPanel>

C#

private void OnGetSet(object sender, RoutedEventArgs e)
{
    RichEditor.Document.GetText(TextGetOptions.FormatRtf, out value);
    RichEditor.Document.SetText(TextSetOptions.FormatRtf, value);
} 

I tried all sort of options both in the SetText and in the GetText, but I am able to prevent additional carriage return to be inserted. Does anyone have a suggestion?

3
I ended up finding a workaround, that I posted below.ClaudiaWey
For information, and help people track a potential bug fix: the problem has been reported to the Microsoft team on their Github repository and can be followed there. See github.com/microsoft/microsoft-ui-xaml/issues/1941.dgellow

3 Answers

4
votes

I ended up finding a reasonable workaround. I am getting the full range of text, then invoke the GetText on the range instead of the document.

I am not sure if this is the best solution, but it works fine.

Updated C#

private void OnGetSet(object sender, RoutedEventArgs e)
{
    var value = GetText(RichEditor);
    RichEditor.Document.SetText(TextSetOptions.FormatRtf, value);
}

public string GetText(RichEditBox editor)
{
    // get the actual size of the text
    editor.Document.GetText(TextGetOptions.UseLf, out string text);

    // get the text in the total range - to avoid getting extra lines
    var range = editor.Document.GetRange(0, text.Length);
    range.GetText(TextGetOptions.FormatRtf, out string value);

    // return the value
    return value;
}
1
votes

I found a solution for this that doesn't seem to conflict with lists and doesn't involve any sort of manual cleaning of the RTF text.

As seen in ClaudiaWey's answer, the length of the text is correct when getting the text in plain text format, at least when using LF. The problem only appears when getting the text in RTF.

So my solution was to store the non-RTF length alongside the RTF text content and then delete the difference between that length and the new (wrong) length when loading the RTF content back into the text box.

In code form, that looks something like this:

TextBox.TextDocument.GetText(TextGetOptions.FormatRtf, out string savedRichText);
TextBox.TextDocument.GetText(TextGetOptions.UseLf, out string savedText);
var savedLength = savedText.Length;

// persist savedLength to the database or wherever alongside savedRichText...

TextBox.TextDocument.SetText(TextSetOptions.FormatRtf, savedRichText);
// Delete the extra bit that gets added because of a bug
TextBox.TextDocument.GetText(TextGetOptions.UseLf, out string text);
TextBox.TextDocument.GetRange(savedLength, text.Length).Text = "";
0
votes

In the meantime I found another workaround, but yours is much less hacky :-) . I just remove the last added newline:

RichEditor.Document.GetText(TextGetOptions.FormatRtf, out var value);
var lastNewLine = value.LastIndexOf("\\par", StringComparison.Ordinal);
value = value.Remove(lastNewLine, "\\par".Length);
RichEditor.Document.SetText(TextSetOptions.FormatRtf, value);            

But this depends on the "wrong" behavior of the RichEditBox, so your solution is much better.