0

I am having prohibitive performance issues with WPF's RichTextBox on WPF forms.

So what I trying now is to replace all rich text controls with TextBlocks, and replace the TextBlock with a RichTextBox when the user clicks.

To achieve this, I made a LazyRichTextBox like this.

class LazyRichTextBox : UserControl
{
    // lots of detail skipped


    protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
    {
        if (!(Content is RichTextBox))
        {
            var box = new RichTextBox { Document = FlowDocumentHtmlConverter.ReplaceDocContent(RichText) };

            Content = box;
        }            
        base.OnPreviewMouseDown(e);
    }

}

The good news is that this works to some extent: I now get an editable textbox. But what does not work is that it does not get the caret in the correct location. The control does not even get the focus from the mouseclick, the user must click again before he/she can start typing.

Now, magically replacing the control on a click may not be the only solution. I could also try to figure out the clicked character position on the TextBlock, then create the RichTextBox and set the focus and caret accordingly. Is that possible?

For the record: I am aware that there's more work to be done: I need to make sure that the TextBlocks appear identical to the RichTextBox appearing later, that tab behavior needs to be handled. I am now focusing on getting the Click scenario as good as possible.

Update: Thanks for the comments. I have very limited rich text, so I know I can emulate them with TextBlocks. The performance issue is due to suspected memory leak, causing a 2GB of memory footprint after two hours of use. I am using RichTextBox/FlowDocument because I don't know any other way to edit text with inline formatting, would be interested in alternatives.

  • Yes, it should be possible to do what you want. Making them look identical will be very challenging though I'd suspect unless you have all but the simplest rich text (as the Rich Text Box is very capable (per its name), while the TextBlock, from my experience, not so much). Are all of the RTBs showing at one time? Can you create them based on scrolling? (Or worse, have a "click to edit" button?) – WiredPrairie Apr 14 '13 at 21:01
  • What is causing the poor performance RichTextBox? Agree with WirePrairie on format. If the format is so simple it will render to TextBlock then why FlowDocument? If it is the creation of the FlowDocument that is causing the performance issues then create the FlowDocument in the BackGround. Or do a priority binding where you just post the first page and then go back for more (both the the BackGround) - that is what I do - I give the a page working - first page - and then everything. – paparazzo Apr 14 '13 at 22:40

1 Answers1

0

It turned out there is a solution to get the insert position: In the MouseDown, I convert my control to a 'RichTextBox'. I call UpdateLayout(), then set the Focus on it, and then, WPF can calculate the insert position like this:

        rtb.CaretPosition = rtb.GetPositionFromPoint(clientPoint, true);

There are a few additional gotchas, I can elaborate if anybody is interested.