ListBox的滚动方式 分为像素滚动和列表项滚动

通过ListBox的附加属性ScrollViewer.CanContentScroll来设置。因此ListBox的默认模板中,含有ScrollViewer,ScrollViewer下存放列表内容

    <ScrollViewer FocusVisualStyle="{x:Null}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}"/>
</ScrollViewer>

而CanContentScroll,true支持逻辑单元(Item),false支持物理单元(像素)。源码如下:

    /// <summary>
/// 获取或设置一个值,该值指示是否支持元素 <see cref="T:System.Windows.Controls.Primitives.IScrollInfo" /> 接口允许滚动。
/// </summary>
/// <returns>
/// <see langword="true" /> 如果 <see cref="T:System.Windows.Controls.ScrollViewer" /> 执行滚动操作使得在逻辑单元; 方面 <see langword="false" /> 如果 <see cref="T:System.Windows.Controls.ScrollViewer" /> 执行滚动操作使得在物理单元方面。
/// 默认值为 <see langword="false" />。
/// </returns>
public bool CanContentScroll
{
get
{
return (bool) this.GetValue(ScrollViewer.CanContentScrollProperty);
}
set
{
this.SetValue(ScrollViewer.CanContentScrollProperty, value);
}
}

滚动

1、像素滚动(物理单元) ScrollViewer.CanContentScroll=false

通过查看源码,我们可以得知CanContentScroll的默认值为false。所以列表ListBox/ListView/DataGrid默认像素滚动

    /// <summary>
/// 标识 <see cref="P:System.Windows.Controls.ScrollViewer.CanContentScroll" /> 依赖属性。
/// </summary>
/// <returns>
/// <see cref="P:System.Windows.Controls.ScrollViewer.CanContentScroll" /> 依赖项属性的标识符。
/// </returns>
[CommonDependencyProperty]
public static readonly DependencyProperty CanContentScrollProperty = DependencyProperty.RegisterAttached(nameof (CanContentScroll), typeof (bool), typeof (ScrollViewer), (PropertyMetadata) new FrameworkPropertyMetadata(BooleanBoxes.FalseBox));
  [FriendAccessAllowed]
internal static class BooleanBoxes
{
internal static object TrueBox = (object) true;
internal static object FalseBox = (object) false; internal static object Box(bool value)
{
if (value)
return BooleanBoxes.TrueBox;
return BooleanBoxes.FalseBox;
}
}

像素滚动的优点:平滑--因为按照像素滚动,肉眼分辨较低。

像素滚动的缺点:耗性能-列表中每个项,都要计算出宽高具体数值,且滚动时时计算。如果列表中数量过多,就相当卡了。

2、列表项滚动(逻辑单元) ScrollViewer.CanContentScroll="True"

按照Item高宽为滚动单位。

列表项滚动时,列表只会滚动到一个完整的Item,不会有一个Item只显示一半的情况。

虚拟化 

通过VirtualizingPanel,设置列表ListBox/ListView/DataGrid是否开启虚拟化

VirtualizingPanel其它属性有:

VirtualizingPanel.ScrollUnit="Pixel"--虚拟化滚动单位(像素/单元)

VirtualizingPanel.IsVirtualizing="True" --是否虚拟

VirtualizingPanel.VirtualizationMode="Recycling"

VirtualizingPanel.CacheLengthUnit="Item" --缓存单位

VirtualizingPanel.CacheLength="20,20"-上下缓存数量

开启虚拟化:为何需要设置ScrollViewer.CanContentScroll="True"?

开启虚拟化后,VirtualizingPanel.ScrollUnit会替换原有的ScrollViewer.CanContentScroll滚动方式

虚拟化也有物理单元与逻辑单元之分,滚动单元设置会转移到VirtualizingPanel.ScrollUnit

但是ScrollViewer.CanContentScroll="False"像素滚动,并不仅仅是滚动消耗性能。当数据很多时加载列表,即使开启了虚化化,因计算太耗性能,界面一样卡顿。

有一个解决办法,设置ScrollViewer.CanContentScroll="True"后,在虚拟化设置中,可以设置虚拟化滚动单元VirtualizingPanel.ScrollUnit="Pixel",此即为虚拟化时的像素滚动。

另:虚拟化时的列表项滚动,VirtualizingPanel.ScrollUnit="Item"列表项

注:

VirtualizingPanel.ScrollUnit和ScrollViewer.CanContentScroll的设置滚动单元一样。

设置虚拟单位为逻辑单元时,滚动时会自动滚动到一个完整的项,而不是滚动到项的部分。

因此当列表可见区域,Items数量或者高宽会变化时,列表滚动时会闪现。

列表正确开启虚拟化方式,请看我的另一博客:WPF 列表开启虚拟化的方式

WPF ListBox/ListView/DataGrid 虚拟化时的滚动方式的更多相关文章

  1. WPF 列表虚拟化时的滚动方式

    ListBox的滚动方式 分为像素滚动和列表项滚动 通过ListBox的附加属性ScrollViewer.CanContentScroll来设置.因此ListBox的默认模板中,含有ScrollVie ...

  2. WPF中ItemsControl应用虚拟化时找到子元素的方法

    原文:WPF中ItemsControl应用虚拟化时找到子元素的方法  wpf的虚拟化技术会使UI的控件只初始化看的到的子元素, 而不是所有子元素都被初始化,这样会提高UI性能. 但是我们经常会遇到一个 ...

  3. fullpage.js最后一屏不满一屏时,滚动方式

    这两天公司网页改版用到fullpage.js这个滚屏插件,页面内容整屏的滚动,不成问题,各种设置在网上也都有文档.而我遇到的问题就是,页面内容不满屏的时候,和上面的内容放一块就太挤,单独放一屏就太空, ...

  4. WPF ItemsControl ListBox ListView比较

    在进行列表信息展示时,WPF中提供多种列表可供选择.这篇博客将对WPF ItemsControl, ListBox, ListView进行比较. 相同点: 1. 这三个控件都是列表型控件,可以进行列表 ...

  5. WPF listbox UI虚拟化

    ListBox  默认是UI虚拟化的. 1. 原生使用  <ListBox VirtualizingPanel.IsVirtualizing="True" Virtualiz ...

  6. WPF中ListBox /ListView如何改变选中条背景颜色

    适用ListBox /ListView WPF中LISTVIEW如何改变选中条背景颜色 https://www.cnblogs.com/sjqq/p/7828119.html

  7. WPF拖动DataGrid滚动条时内容混乱的解决方法

    WPF拖动DataGrid滚动条时内容混乱的解决方法 在WPF中,如果DataGrid里使用了模板列,当拖动滚动条时,往往会出现列表内容显示混乱的情况.解决方法就是在Binding的时候给Update ...

  8. 在WPF中弹出右键菜单时判断鼠标是否选中该项

      和上篇在WPF的TreeView中实现右键选定一样,这仍然是一个右键菜单的问题: 这个需求是在一个实现剪贴板的功能的时候遇到的:在弹出右键菜单时,如果菜单弹出位置在ListViewItem中时,我 ...

  9. 自定义WPF ListBox的选择样式

    (下图:进行多项选择的ListBox) 首先介绍一种简单地方法:就是通过自定义SystemColors类的参数来自定义WPF ListBox选择颜色的,SystemColors的HighlightBr ...

随机推荐

  1. T410升级笔记

      T410 win7 旗舰版 32 sp1 三星  DDR3 1066 mhz core i5 M 540 2.53GHZ 双核 日立 HTS725032A9A364 320G/7200转/分 sa ...

  2. OAuth2.0学习(1-11)新浪开放平台微博认证-使用OAuth2.0调用微博的开放API

    使用OAuth2.0调用API 使用OAuth2.0调用API接口有两种方式: 1. 直接使用参数,传递参数名为 access_token URL 1 https://api.weibo.com/2/ ...

  3. Python之socketserver模块和验证客户端链接的合法性

    验证客户端链接的合法性 分布式系统中实现一个简单的客户端链接认证功能 #_*_coding:utf-8_*_ from socket import * import hmac,os secret_ke ...

  4. python爬虫——分析天猫iphonX的销售数据

    01.引言 这篇文章是我最近刚做的一个项目,会带领大家使用多种技术实现一个非常有趣的项目,该项目是关于苹果机(iphoneX)的销售数据分析,是网络爬虫和数据分析的综合应用项目.本项目会分别从天猫和京 ...

  5. spring cloud之坑,访问服务时找不到报404

    主要是因为: 启动时 而我访问时,api是按照下面这样访问的: 所以报404找不到

  6. 关于PHP包含文件的方法

    Begin 今天陆陆续续在重新写一些后台程序,用到了一些共用的PHP文件,所以顺便学习了一下几种包含文件方式 include 最常用的包含文件方法,如果遇到错误会显示warning,但是不会影响下面脚 ...

  7. Windows10下的docker安装与入门 (二)使用docker引擎在容器中运行镜像

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何 ...

  8. Java面试题—初级(1)

    1.一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制? 可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致. 2.Java有 ...

  9. JSON序列化类

    '''pyhton的dict对象可以直接序列化为JSON的{},不过很多时候 我们更喜欢用class表示对象,比如定义Student类,然后序列化''' import json class Stude ...

  10. [LeetCode] Shopping Offers 购物优惠

    In LeetCode Store, there are some kinds of items to sell. Each item has a price. However, there are ...