【问题标题】:Scroll first listbox item into view将第一个列表框项目滚动到视图中
【发布时间】:2014-12-19 12:27:11
【问题描述】:

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

【问题讨论】:

  • 您可能正试图在窗口构造函数中调用它。在Loaded 这样做。
  • ItemsSource 更新时会正确调用。它只是不会滚动到顶部。
  • 在表单加载后尝试设置ItemsSource(又名Loaded)。
  • ItemsSource 是通过数据绑定设置的,所以除了基础对象更改时,我无法控制它何时真正设置。
  • 然后只需调用Loaded末尾的事件处理程序即可。更干净的是创建单独的方法 ScrollToTop() 并从属性更改事件中调用它,并直接在 Loaded 中调用一次。

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


【解决方案1】:

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

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

【讨论】:

  • 您的建议并没有解决问题,但确实让我找到了解决方案。查看我的编辑。
【解决方案2】:

一个简单的方法是:

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

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

【讨论】:

  • 问题是 ItemSourceChanged 没有自动触发?
  • 不,事件正确触发,代码被执行。我怀疑它是在 UI 发生更改之前调用的,并且由于明显的原因无法将其滚动到视图中。我已经找到了出路,会在几分钟内更新帖子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多