当我们改变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)。

     /// <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 >= )
listBox.ScrollIntoView(listBox.Items[index]);
} #endregion

解决WPF程序中ListBox ItemsSource变化时不重置ScrollBar的问题的更多相关文章

  1. WPF 程序中启动和关闭外部.exe程序

    当需要在WPF程序启动时,启动另一外部程序(.exe程序)时,可以按照下面的例子来: C#后台代码如下: using System; using System.Collections.Generic; ...

  2. 如何在WPF程序中使用ArcGIS Engine的控件

    原文 http://www.gisall.com/html/47/122747-4038.html WPF(Windows Presentation Foundation)是美国微软公司推出.NET ...

  3. WPF程序中App.Config文件的读与写

    WPF程序中的App.Config文件是我们应用程序中经常使用的一种配置文件,System.Configuration.dll文件中提供了大量的读写的配置,所以它是一种高效的程序配置方式,那么今天我就 ...

  4. 如何追踪 WPF 程序中当前获得键盘焦点的元素并显示出来

    原文:如何追踪 WPF 程序中当前获得键盘焦点的元素并显示出来 title: "如何追踪 WPF 程序中当前获得键盘焦点的元素并显示出来" publishDate: 2019-06 ...

  5. 在WPF程序中使用摄像头兼谈如何使用AForge.NET控件(转)

    前言: AForge.NET 是用C#写的一个关于计算机视觉和人工智能领域的框架,它包括图像处理.神经网络.遗传算法和机器学习等.在C#程序中使用摄像头,我习惯性使用AForge.NET提供的类库.本 ...

  6. 解决WPF的ScrollViewer在使用触摸屏时,滑到尽头窗口抖动的情况

    原文:解决WPF的ScrollViewer在使用触摸屏时,滑到尽头窗口抖动的情况 wpf的ScrollViewer在触摸条件下 默认在尽头时会有一个窗口一起被拖动的FeedBack,但对用户的交互很不 ...

  7. 在 WPF 程序中应用 Windows 10 真?亚克力效果

    原文:在 WPF 程序中应用 Windows 10 真?亚克力效果 从 Windows 10 (1803) 开始,Win32 应用也可以有 API 来实现原生的亚克力效果了.不过相比于 UWP 来说, ...

  8. qt之窗口换肤(一个qss的坑:当类属性发现变化时需要重置qss,使用rcc资源文件)

    1.相关文章 Qt 资源系统qt的moc,uic,rcc命令的使用 2.概要    毕业两年了,一直使用的是qt界面库来开发程序,使用过vs08.10.13等开发工具,并安装了qt的插件,最近在做客户 ...

  9. WPF程序中的弱事件模式

    在C#中,得益于强大的GC机制,使得我们开发程序变得非常简单,很多时候我们只需要管使用,而并不需要关心什么时候释放资源.但是,GC有的时并不是按照我们所期望的方式工作. 例如,我想实现一个在窗口的标题 ...

随机推荐

  1. Linux ppp 数据收发流程

    转:http://blog.csdn.net/yangzheng_yz/article/details/11526671 PPP (Point-to-Point)提供了一种标准的方法在点对点的连接上传 ...

  2. QT学习之路DAY1之初学QT的小项目

    以下所有代码均利用软件QT5编写 项目一:Hello world! 利用QTcreator创建项目 修改main.cpp代码为 #include "mainwindow.h" #i ...

  3. 原生js制作播放器

    以前 就想做一个播放器,一直没狠下心来,今天终于狠下心来,把这个做出来了(因为有点无聊) 做这个播放器  也百度了一下, 你叫我做,我肯定做不出来, 就算用jquery  我也做不出来. 以前也用过a ...

  4. bat %n 判断传入的参数值和使用注意

    bat %n 判断传入的参数值和使用注意 if "%1" == "" echo empty 1 if exist "%1" echo 1pa ...

  5. GPU Debugger

    https://gpuopen.com/presentations/2019/digital-dragons-2019-make-your-game-friendly.pdf https://grap ...

  6. Java8-Stream-No.06

    import java.io.IOException; import java.math.BigDecimal; import java.util.Arrays; import java.util.s ...

  7. centos 升级内核方法

    方法1:rpm安装方式 rpm安装包可以通过这个网站下载: 这个是CentOS6 x64 : http://elrepo.org/linux/kernel/el6/x86_64/RPMS/ 这个是Ce ...

  8. 小米 oj 硬币比赛(思维+动态规划)

     硬币比赛 序号:#47难度:困难时间限制:1000ms内存限制:10M 描述 有 n 个不同价值的硬币排成一条线.有 A 与 B 两个玩家,指定由 A 开始轮流(A 先手,然后 B,然后再 A..) ...

  9. 「BZOJ 5010」「FJOI 2017」矩阵填数「状压DP」

    题意 你有一个\(h\times w\)的棋盘,你需要在每个格子里填\([1, m]\)中的某个整数,且满足\(n\)个矩形限制:矩形的最大值为某定值.求方案数\(\bmod 10^9+7\) \(h ...

  10. Win10 + CLion + 树莓派 + QT 远程开发调用Python

    原则:能在一个机器上开发的就不在两台机器上!! 首先需要配置远程QT开发环境 配置Cmake cmake_minimum_required(VERSION 3.14) project(qt_test) ...