我维护了一个遗留应用程序并请求添加功能。我有一个显示一些项目的列表框。当Itemssource被更改时,我希望列表框滚动到顶部。
为此,我订阅了该活动:
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有机会更新之前尝试滚动的问题。因此,使用Dispatcher,我们可以设置优先级,以便在我们尝试将项目滚动到视图之前更新UI。
Dispatcher.BeginInvoke((Action)(() => KommentarListBox.ScrollIntoView(item)), System.Windows.Threading.DispatcherPriority.ContextIdle, null);
答案 0 :(得分:1)
不要直接调用ScrollIntoView函数,而是尝试通过调度程序调用它。 对于winforms应用程序,这将是:
BeginInvoke((Action)(() => KommentarListBox.ScrollIntoView(item)));
答案 1 :(得分:0)
一个简单的方法就是:
if (KommentarListBox.Items.Count > 0)
lstBox.ScrollIntoView(KommentarListBox.Items[0]);
我同意Sinatr的最后评论,创建单独的方法并调用它两次,一次在事件处理程序中,一次在Loaded事件结束时。