繁体   English   中英

如何在WPF中执行顺序的BringIntoView调用?

[英]How do I perform sequential BringIntoView calls in WPF?

我们的应用程序中有一个TreeView ,具有以下要求:

添加项目时:

  1. 新添加的项目将滚动到视图中
  2. 新添加的项的父项也滚动到视图中。
  3. 如果它们距离太远而无法同时看到两者,则该项目优先。

这似乎很简单,只需先将父级滚动到视图中,然后滚动子级即可。

问题是当您这样称呼它时:

parent.BringIntoView();
child.BringIntoView();

...似乎只有第二个起作用。 第一个基本上被忽略。

然后,我尝试将第二个调用包装在BeginInvoke()调用中,如下所示:

parent.BringIntoView();

Dispatcher.BeginInvoke((Action)(() => {
    child.BringIntoView();
}));

哪个可行,但是现在您可以看到TreeView滚动两次; 一次是给父母,然后是片刻,给孩子,这看起来很糟。

那么,如何才能BringIntoView背对背地调用BringIntoView ,而又不会出现使用分派器的双重刷新问题?

尝试使用Loaded事件而不是调度程序。 根据本文的介绍 ,它非常适合以下情况:

...我们最初实现了Loaded事件,以便在渲染窗口之后但在处理任何输入之前将其触发。 我们认为,如果准备好进行输入,就足以进行加载时初始化。 但是随后我们开始从Loaded事件触发动画,并看到了问题。 一会儿,您会看到没有动画的内容呈现,然后您会看到动画开始。 您可能并不总是注意到它,但是当您远程运行该应用程序时,它尤其明显。

因此,我们移动了Loaded,使其现在可以在布局和数据绑定有机会运行之后但在第一次渲染之前触发。 (请注意,如果您在Loaded事件处理程序中执行任何使布局无效的操作,则可能需要在呈现之前重新运行它。)

换句话说,在“加载”中,您具有有关元素物理布局的最新信息,但实际上尚未呈现,因此应该避免出现任何“屏幕闪烁”问题。

编辑 :要在评论中回答您的问题,您可以使用闭包将“本地”事件连接到当前方法,如下所示:

EventHandler handler = null;
handler = (sender, e) => {
    this.LayoutUpdated -= handler;  // only run once
    child.BringIntoView();
};
this.LayoutUpdated += handler;

通过在方法内部定义处理程序,您可以从内部访问方法的局部变量( child )。 Dispatcher调用非常相似。

实际上,我不确定依赖LayoutUpdated是否是个好主意。 它经常发生,因此可能会比您需要的更快发射。 例如,对于单独的WidthHeight设置,它会发生两次。 另一个需要研究的是ScrollViewer.ScrollChanged 或者,您可以完全避免使用BringIntoView并尝试手动检查元素大小以计算滚动到的位置。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM