Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 647|回复: 0

解决WPF程序中ListBox ItemsSource变化时不重置ScrollBar的问题

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-6-16 05:49:26 | 显示全部楼层 |阅读模式

    当我们改变ListBox的ItemsSource时,会发现这样一个问题:数据源变化时,虽然控件中的内容会跟着变化,但滚动条却不会重置

    举个例子:

    1. 将ListBox绑定到一百个字符串: listbox.ItemsSource = Enumerable.Range(0, 100).Select(i => "## " + i);
    2. 将ListBox的滚动条拖到最后,使之能看到最后的"## 99",看不到最开始的"## 0"。
    3. 将ListBox绑定到另外一百个字符串: listbox.ItemsSource = Enumerable.Range(0, 100).Select(i => ">> " + i); 这时我们会发现:虽然数据内容会变更,但滚动条仍然在最后,能看到最后的">> 99",看不到最开始的">> 0"。

    大多数情况下,这个并不是我们所期望的结果。如何解决这个问题,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)。

     

    View Code 
     1      ///   <summary>
     2       ///  This class contains a few useful extenders for the ListBox
     3       ///   </summary>
     4       public  class ListBoxExtenders : DependencyObject
     5     {
     6          #region Properties
     7 
     8          public  static  readonly DependencyProperty AutoScrollToCurrentItemProperty = DependencyProperty.RegisterAttached( " AutoScrollToCurrentItem ",
     9              typeof( bool),  typeof(ListBoxExtenders),  new UIPropertyMetadata( default( bool), OnAutoScrollToCurrentItemChanged));
    10 
    11          ///   <summary>
    12           ///  Returns the value of the AutoScrollToCurrentItemProperty
    13           ///   </summary>
    14           ///   <param name="obj"> The dependency-object whichs value should be returned </param>
    15           ///   <returns> The value of the given property </returns>
    16           public  static  bool GetAutoScrollToCurrentItem(DependencyObject obj)
    17         {
    18              return ( bool)obj.GetValue(AutoScrollToCurrentItemProperty);
    19         }
    20 
    21          ///   <summary>
    22           ///  Sets the value of the AutoScrollToCurrentItemProperty
    23           ///   </summary>
    24           ///   <param name="obj"> The dependency-object whichs value should be set </param>
    25           ///   <param name="value"> The value which should be assigned to the AutoScrollToCurrentItemProperty </param>
    26           public  static  void SetAutoScrollToCurrentItem(DependencyObject obj,  bool value)
    27         {
    28             obj.SetValue(AutoScrollToCurrentItemProperty, value);
    29         }
    30 
    31          #endregion
    32 
    33          #region Events
    34 
    35          ///   <summary>
    36           ///  This method will be called when the AutoScrollToCurrentItem
    37           ///  property was changed
    38           ///   </summary>
    39           ///   <param name="sender"> The sender (the ListBox) </param>
    40           ///   <param name="e"> Some additional information </param>
    41           public  static  void OnAutoScrollToCurrentItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    42         {
    43              var listBox = sender  as ListBox;
    44              if ((listBox ==  null) || (listBox.Items ==  null))
    45                  return;
    46 
    47              var enable = ( bool)e.NewValue;
    48              var autoScrollToCurrentItemWorker =  new EventHandler((_1, _2) => OnAutoScrollToCurrentItem(listBox, listBox.Items.CurrentPosition));
    49 
    50              if (enable)
    51                 listBox.Items.CurrentChanged += autoScrollToCurrentItemWorker;
    52              else
    53                 listBox.Items.CurrentChanged -= autoScrollToCurrentItemWorker;
    54         }
    55 
    56          ///   <summary>
    57           ///  This method will be called when the ListBox should
    58           ///  be scrolled to the given index
    59           ///   </summary>
    60           ///   <param name="listBox"> The ListBox which should be scrolled </param>
    61           ///   <param name="index"> The index of the item to which it should be scrolled </param>
    62           public  static  void OnAutoScrollToCurrentItem(ListBox listBox,  int index)
    63         {
    64              if (listBox !=  null && listBox.Items !=  null && listBox.Items.Count > index && index >=  0)
    65                 listBox.ScrollIntoView(listBox.Items[index]);
    66         }
    67 
    68          #endregion
    69

     

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-12-23 02:28 , Processed in 0.054653 second(s), 28 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表