wpflayoutrichtextboxloaded

Wait until control layout is finished


I am loading quite a lot of rich text into a RichTextBox (WPF) and I want to scroll to the end of content:

richTextBox.Document.Blocks.Add(...)
richTextBox.UpdateLayout();
richTextBox.ScrollToEnd();

This doesn't work, ScrollToEnd is executed when the layout is not finished, so it doesn't scroll to the end, it scrolls to around the first third of the text.

Is there a way to force a wait until the RichTextBox has finished its painting and layout operations so that ScrollToEnd actually scrolls to the end of the text?

Thanks.

Stuff that doesn't work:

EDIT: I have tried the LayoutUpdated event but it's fired immediately, same problem: the control is still laying out more text inside the richtextbox when it's fired so even a ScrollToEnd there doesn't work... I tried this:

richTextBox.Document.Blocks.Add(...)
richTextBoxLayoutChanged = true;
richTextBox.UpdateLayout();
richTextBox.ScrollToEnd();

and inside the richTextBox.LayoutUpdated event handler:

if (richTextBoxLayoutChanged)
{
    richTextBoxLayoutChanged = false;
    richTextBox.ScrollToEnd();
}

The event is fired correctly but too soon, the richtextbox is still adding more text when it's fired, layout is not finished so ScrollToEnd fails again.

EDIT 2: Following on dowhilefor's answer: MSDN on InvalidateArrange says

After the invalidation, the element will have its layout updated, which will occur asynchronously unless subsequently forced by UpdateLayout.

Yet even

richTextBox.InvalidateArrange();
richTextBox.InvalidateMeasure();
richTextBox.UpdateLayout();

does NOT wait: after these calls the richtextbox is still adding more text and laying it out inside itself asynchronously. ARG!


Solution

  • Have a look at UpdateLayout

    especially:

    Calling this method has no effect if layout is unchanged, or if neither arrangement nor measurement state of a layout is invalid

    So calling InvalidateMeasure or InvalidateArrange, depending on your needs should work.

    But considering your piece of code. I think that won't work. Alot of WPF loading and creating is deffered, so adding something to Document.Blocks does not necesarilly change the UI directly. But i must say, this is just a guess and maybe i'm wrong.