我们的应用程序中有TreeView
符合以下要求:
添加项目时:
这看起来很简单,只需先将父级滚动到视图中,然后滚动子级。
问题在于你这样称呼它:
parent.BringIntoView();
child.BringIntoView();
......只有第二个似乎有任何影响。第一个基本上被忽略了。
然后我尝试在BeginInvoke()
这样的电话中打包第二个电话:
parent.BringIntoView();
Dispatcher.BeginInvoke((Action)(() => {
child.BringIntoView();
}));
哪个确实有效,但现在你可以看到TreeView
两次滚动;一次为父母,一会儿之后,对于那个看起来很糟糕的孩子。
那么我如何能够背靠背调用BringIntoView
但没有使用调度程序的双重刷新问题?
答案 0 :(得分:0)
尝试使用Loaded
事件而不是调度程序。根据{{3}},它非常适合这样的情况:
...我们最初实现了Loaded事件 它会在窗口渲染之后,但在任何输入之前触发 被处理了。我们认为,如果它足够准备输入,它 已准备好足以进行加载时初始化。但后来我们开始了 触发Loaded事件的动画,并看到问题;为一个 然后,拆分秒,你会看到没有动画的内容渲染 你会看到动画开始。你可能并不总是注意到它,但它 当您远程运行应用程序时,这一点尤为明显。
所以我们感动了 加载,以便它现在在布局和数据绑定之后触发了 有机会跑,但就在第一次渲染之前。 (并注意如果 你在Loaded事件处理程序中做任何使布局无效的事情, 在渲染之前可能需要重新运行它。)
换句话说,在Loaded上你有关于元素物理布局的最新信息,但它实际上还没有渲染,所以你应该避免任何“屏幕闪烁”问题。
编辑:要在评论中回答您的问题,您可以使用闭包将事件“local”连接到当前方法,如下所示:
EventHandler handler = null;
handler = (sender, e) => {
this.LayoutUpdated -= handler; // only run once
child.BringIntoView();
};
this.LayoutUpdated += handler;
通过在方法内定义处理程序,您可以从内部访问方法的局部变量(child
)。与Dispatcher
电话非常相似。
实际上,我不确定依靠LayoutUpdated
是否是一个好主意。它经常发生,所以它可能会比你需要的更快地射击。例如,对于单个Width
和Height
设置,它会发生两次。另一个要研究的是this article。或者您可以完全避免BringIntoView
并尝试手动检查元素大小以计算滚动到的位置。