等到控制布局完成

Sem*_*ike 9 wpf layout richtextbox loaded

我正在将很多富文本加载到RichTextBox(WPF)中,我想滚动到内容的结尾:

richTextBox.Document.Blocks.Add(...)
richTextBox.UpdateLayout();
richTextBox.ScrollToEnd();
Run Code Online (Sandbox Code Playgroud)

这不起作用,ScrollToEnd在布局未完成时执行,因此它不会滚动到结尾,它会滚动到文本的前三分之一左右.

有没有办法强制等待,直到RichTextBox完成绘画和布局操作,以便ScrollToEnd实际滚动到文本的末尾?

谢谢.

不起作用的东西:

编辑:我已经尝试过这个LayoutUpdated事件,但它立刻被解雇了,同样的问题:当它被解雇时,控件仍然在richtextbox里面放置更多的文本,所以即使ScrollToEnd它没有工作......我试过这个:

richTextBox.Document.Blocks.Add(...)
richTextBoxLayoutChanged = true;
richTextBox.UpdateLayout();
richTextBox.ScrollToEnd();
Run Code Online (Sandbox Code Playgroud)

并在richTextBox.LayoutUpdated事件处理程序内:

if (richTextBoxLayoutChanged)
{
    richTextBoxLayoutChanged = false;
    richTextBox.ScrollToEnd();
}
Run Code Online (Sandbox Code Playgroud)

事件被正确触发但是过早,richtextbox在触发时仍然添加更多文本,布局未完成,因此ScrollToEnd再次失败.

编辑2:关注dowhilefor的回答:InvalidateArrange上的MSDN说

失效后,元素将更新其布局,除非随后由UpdateLayout强制,否则将以异步方式进行.

甚至

richTextBox.InvalidateArrange();
richTextBox.InvalidateMeasure();
richTextBox.UpdateLayout();
Run Code Online (Sandbox Code Playgroud)

不要等待:在这些调用之后,richtextbox仍然会添加更多文本并异步地将其放在自身内部.ARG!

Pat*_*son 8

我有一个相关的情况:我有一个打印预览对话框,创建一个奇特的渲染.通常,用户将单击一个按钮来实际打印它,但我也想用它来保存图像而无需用户参与.在这种情况下,创建图像必须等到布局完成.

我使用以下方法管理:

Dispatcher.Invoke(new Action(() => {SaveDocumentAsImage(....);}), DispatcherPriority.ContextIdle);
Run Code Online (Sandbox Code Playgroud)

关键是DispatcherPriority.ContextIdle,等待后台任务完成.

编辑:根据Zach的请求,包括适用于此特定案例的代码:

Dispatcher.Invoke(() => { richTextBox.ScrollToEnd(); }), DispatcherPriority.ContextIdle);
Run Code Online (Sandbox Code Playgroud)

我应该注意到,我对这个解决方案并不满意,因为它感觉非常脆弱.但是,它似乎确实适用于我的具体情况.


dow*_*for 3

看看UpdateLayout

尤其:

如果布局未更改,或者布局的排列和测量状态均无效,则调用此方法无效

因此,根据您的需要调用 InvalidateMeasure 或 InvalidateArrange 应该可行。

但考虑到你的代码。我认为这行不通。许多 WPF 加载和创建都被延迟,因此向 Document.Blocks 添加某些内容并不一定会直接更改 UI。但我必须说,这只是一个猜测,也许我是错的。