将第一个列表框项目滚动到视图中

时间:2014-12-19 12:27:11

标签: c# .net wpf listbox .net-4.5

我维护了一个遗留应用程序并请求添加功能。我有一个显示一些项目的列表框。当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);

2 个答案:

答案 0 :(得分:1)

不要直接调用ScrollIntoView函数,而是尝试通过调度程序调用它。 对于winforms应用程序,这将是:

BeginInvoke((Action)(() => KommentarListBox.ScrollIntoView(item)));

答案 1 :(得分:0)

一个简单的方法就是:

if (KommentarListBox.Items.Count > 0)
    lstBox.ScrollIntoView(KommentarListBox.Items[0]);

我同意Sinatr的最后评论,创建单独的方法并调用它两次,一次在事件处理程序中,一次在Loaded事件结束时。