标签:
当我们改变ListBox的ItemsSource时,会发现这样一个问题:数据源变化时,虽然控件中的内容会跟着变化,但滚动条却不会重置。
举个例子:
大多数情况下,这个并不是我们所期望的结果。如何解决这个问题,stackoverflow文章Reset scrollbar on ItemsSource change给了一个解决方案:找到ListBox的ScrollViewer,响应ListBox的SourceUpdated事件,滚动滚动条到顶端。
listbox.SourceUpdated += (_1, _2) => scrollView.ScrollToTop();
这种方法本身没有什么问题,但是由于ScrollViewer是视觉树的一部分,从ListBox上获取并不容易(可能会修改模板)。我后来又从Wordpress文章ListBox – Automatically scroll CurrentItem into View上找到了一个方案:响应ListBox的Items.CurrentChanged事件,通过函数ScrollIntoView实现滚动到顶端。
listbox.Items.CurrentChanged += (_1, _2) => listbox.ScrollIntoView(listbox.Items[0]);
原文本来的目的是为了实现将ListBox自动滚动到CurrentItem,也可用来解决这个问题。原文更是实现了一个附加属性,使得可以在XAML中直接使用,来非常方便。
<ListBox local:ListBoxExtenders.AutoScrollToCurrentItem="True"/>
由于众所周知的原因,Wordpress这个并不存在的网站只能从火星上访问,没有火星专线的朋友可以找方校长借,或者直接参考我下面的代码(稍微修改了点,貌似也没有什么bug)。
1 /// <summary> /// This class contains a few useful extenders for the ListBox /// </summary> public class ListBoxExtenders : DependencyObject { #region Properties public static readonly DependencyProperty AutoScrollToCurrentItemProperty = DependencyProperty.RegisterAttached("AutoScrollToCurrentItem", typeof(bool), typeof(ListBoxExtenders), new UIPropertyMetadata(default(bool), OnAutoScrollToCurrentItemChanged)); /// <summary> /// Returns the value of the AutoScrollToCurrentItemProperty /// </summary> /// <param name="obj">The dependency-object whichs value should be returned</param> /// <returns>The value of the given property</returns> public static bool GetAutoScrollToCurrentItem(DependencyObject obj) { return (bool)obj.GetValue(AutoScrollToCurrentItemProperty); } /// <summary> /// Sets the value of the AutoScrollToCurrentItemProperty /// </summary> /// <param name="obj">The dependency-object whichs value should be set</param> /// <param name="value">The value which should be assigned to the AutoScrollToCurrentItemProperty</param> public static void SetAutoScrollToCurrentItem(DependencyObject obj, bool value) { obj.SetValue(AutoScrollToCurrentItemProperty, value); } #endregion #region Events /// <summary> /// This method will be called when the AutoScrollToCurrentItem /// property was changed /// </summary> /// <param name="sender">The sender (the ListBox)</param> /// <param name="e">Some additional information</param> public static void OnAutoScrollToCurrentItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { var listBox = sender as ListBox; if ((listBox == null) || (listBox.Items == null)) return; var enable = (bool)e.NewValue; var autoScrollToCurrentItemWorker = new EventHandler((_1, _2) => OnAutoScrollToCurrentItem(listBox, listBox.Items.CurrentPosition)); if (enable) listBox.Items.CurrentChanged += autoScrollToCurrentItemWorker; else listBox.Items.CurrentChanged -= autoScrollToCurrentItemWorker; } /// <summary> /// This method will be called when the ListBox should /// be scrolled to the given index /// </summary> /// <param name="listBox">The ListBox which should be scrolled</param> /// <param name="index">The index of the item to which it should be scrolled</param> public static void OnAutoScrollToCurrentItem(ListBox listBox, int index) { if (listBox != null && listBox.Items != null && listBox.Items.Count > index && index >= 0) listBox.ScrollIntoView(listBox.Items[index]); } #endregion 69
解决WPF程序中ListBox ItemsSource变化时不重置ScrollBar的问题
标签:
原文地址:http://www.cnblogs.com/tianciliangen/p/4806586.html