将第一个列表框项滚动到视图中
本文关键字:视图 滚动 第一个 列表 | 更新日期: 2023-09-27 18:34:52
我维护一个遗留应用程序并请求添加功能。我有一个列表框显示一些项目。当项目源被更改时,我希望列表框滚动到顶部。
为此,我订阅了该活动:
private bool handlerAdded = false;
private void KommentarListBox_Loaded(object sender, RoutedEventArgs e)
{
if (handlerAdded) { return; }
var dpd = DependencyPropertyDescriptor.FromProperty(ItemsControl.ItemsSourceProperty, typeof(ListView));
if (dpd != null)
{
dpd.AddValueChanged(KommentarListBox, KommentarListBox_ItemsSourceChanged);
}
handlerAdded = true;
}
和事件处理程序:
private void KommentarListBox_ItemsSourceChanged(object sender, EventArgs e)
{
if (KommentarListBox.ItemsSource == null) { return; }
object item = null;
foreach (var i in KommentarListBox.ItemsSource)
{
item = i;
break;
}
if (item != null)
{
KommentarListBox.ScrollIntoView(item);
}
}
但是,这不会向上滚动。如果我手动调用事件处理程序,例如通过按下按钮,它可以工作。因此,为了好玩,我尝试从另一个线程中睡觉,令我惊讶的是,它也可以工作。然而,这是我宁愿不留在代码库中的代码气味。我怀疑事件处理程序是在 UI 有机会更新 UI 之前调用的,但我不确定。有谁知道如何比可怕的睡眠更有力地解决这个问题,并且知道发生了什么?
溶液
这个问题被怀疑是在UI有机会更新之前尝试滚动的问题。因此,使用调度程序,我们可以设置优先级,以便在我们尝试将项目滚动到视图中之前更新 UI。
Dispatcher.BeginInvoke((Action)(() => KommentarListBox.ScrollIntoView(item)), System.Windows.Threading.DispatcherPriority.ContextIdle, null);
不要直接调用 ScrollIntoView 函数,而是尝试通过调度程序调用它。对于 winforms 应用程序,这将是:
BeginInvoke((Action)(() => KommentarListBox.ScrollIntoView(item)));
一个简单的方法必须是:
if (KommentarListBox.Items.Count > 0)
lstBox.ScrollIntoView(KommentarListBox.Items[0]);
我同意Sinatr的最后一条评论,方法是创建单独的方法并调用它两次,一次在事件处理程序中,一次在Loaded事件结束时。