前言

列表滚动到具体的数据项?

ListBox提供了简易快捷的滚动定位函数ScrollIntoView。

TreeView树状结构列表,则没有此类方法,无法与ListBox一样,直接设置滚动到具体的数据项。

同时,SelectedItem也是只读的,无法设置SelectedItem来间接的设置滚动项。

TreeView滚动定位

1. 对TreeViewItem添加一个附加属性IsScrolledToViewWhenSelected,在属性变更事件中,添加对Loaded事件的订阅和注销

     static void OnIsScrolledToViewWhenSelectedChanged(
DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
if (depObj is TreeViewItem treeViewItem && e.NewValue is bool isIntoViewWhenSelected)
{
treeViewItem.Loaded -= TreeViewItem_Loaded;
if (isIntoViewWhenSelected)
{
treeViewItem.Loaded += TreeViewItem_Loaded;
}
}
}

2. 在Loaded事件中,根据当前TreeViewItem是否选中,调用是否滚动到视图区域的逻辑

     static void TreeViewItem_Loaded(object sender, RoutedEventArgs e)
{
var treeViewItem = e.OriginalSource as TreeViewItem;
if (treeViewItem != null)
{
treeViewItem.Loaded -= TreeViewItem_Loaded;
if (treeViewItem.IsSelected)
{
treeViewItem.BringIntoView();
}
}
}

此处,对TreeView添加附加属性处理,也是可以的

虚拟化后的TreeView滚动定位

因开启了虚拟化,界面上不在当前视觉内的数据项,没有生成相应的视觉树,即无法找到TreeViewItem。

所以虚拟化后,使用TreeViewItem添加附加属性,而不是TreeView。因为TreeView无法对视觉树外的项,查找并定位;而TreeViewItem...emmm~可以使用黑科技处理,详情如下

1. 在上面逻辑的基础上,添加对虚拟化的处理。

此处添加了对虚拟化的判断,虚拟化时如果已经完成了滚动定位,则对后续的逻辑直接跳过,避免选中项的定位被干扰。

     static void OnIsScrolledToViewWhenSelectedChanged(
DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
if (depObj is TreeViewItem treeViewItem && e.NewValue is bool isIntoViewWhenSelected)
{
treeViewItem.Loaded -= TreeViewItem_Loaded;
//获取父控件TreeView
var treeView = treeViewItem.FindVisualParent<TreeView>();
if (isIntoViewWhenSelected)
{
//开启了虚拟化且未完成滚动,直接返回
var isOpeningVitualizing = ScrollViewer.GetCanContentScroll(treeView) && VirtualizingPanel.GetIsVirtualizing(treeView);
if (isOpeningVitualizing && GetHasSetSelectedItemVisible(treeView))
{
return;
}
treeViewItem.Loaded += TreeViewItem_Loaded;
}
}
}

2. 在之前逻辑的基础上,添加虚拟化的判断

如果开启了虚拟化,

  • 列表项未选中时,设置滚动到视图中
  • 列表项选中时,设置已完成,并滚动到视图中

黑科技:

列表数据加载时,每项都滚动到视图中。

而虚拟化列表实际上初始化的项个数,在默认设置下,比可视化区域的项个数要多很一部分。

所以在单个数据加载时,设置滚动视图,会带动更多原本不在视图内的数据项,生成视觉树。

     static void TreeViewItem_Loaded(object sender, RoutedEventArgs e)
{
var treeViewItem = e.OriginalSource as TreeViewItem;
if (treeViewItem != null)
{
treeViewItem.Loaded -= TreeViewItem_Loaded;
//获取父控件TreeView
var treeView = treeViewItem.FindVisualParent<TreeView>();
//是否开启了虚拟化
var isOpeningVirtualizing = ScrollViewer.GetCanContentScroll(treeView) && VirtualizingPanel.GetIsVirtualizing(treeView);
if (isOpeningVirtualizing)
{
if (treeViewItem.IsSelected)
{
//设置已完成滚动,减少剩余项的加载判断
SetHasSetSelectedItemVisible(treeView, true);
treeViewItem.BringIntoView();
}
else
{
treeViewItem.BringIntoView();
}
}
else if(treeViewItem.IsSelected)
{
treeViewItem.BringIntoView();
}
}
}

WPF 列表开启虚拟化的方式

关键字:TreeView虚拟化、滚动到选中项

WPF TreeView 虚拟化-设置滚动到选中项的更多相关文章

  1. 自定义Behavior 实现Listbox自动滚动到选中项

    原文:自定义Behavior 实现Listbox自动滚动到选中项 blend为我们提供方便的behavior来扩展我们的控件,写好之后就可以在blend中方便的使用了. 下面是自定义的behavior ...

  2. angularjs中设置select的选中项

    最近用angularjs比较多,里面有很多自己的方法,都不咋会用,这篇只是个笔记,防止自己忘记 <select style="width:100%" ng-model=&qu ...

  3. jquery动态生成的select下拉框,怎么设置默认的选中项?

    这两天都被这问题困扰,可能是我不太懂前端.我做layui表格行编辑,点击编辑按钮弹出layer,里边有一个民族的下拉框不能直接显示后台传过来的值.我把民族数组用jquery添加到了select里边,可 ...

  4. ASP.NET--ListBox初始化时设置多个选中项

    public void SetSelectedListItem(ListBox lst, List<DBServerIPBind> source) { ; i < source.Co ...

  5. jquery 设置asp:dropdownlist 选中项

    $("#ddlPro").find('option').each(function () { this.selected = (this.text == dlprom); });

  6. 根据值设置select的选中项

    $('.selector').attr("checked", true); <s:iterator value="jobSelect" id=" ...

  7. Winform下的Combox根据值来选中项

    其实很简单,因为Combox的Item是一个K/V的object,那么就可以把它的items转换成IEnumerable<DictionaryEntry>类型的(System.Collec ...

  8. layui动态修改select的选中项

    layui动态修改select的选中项:(在layUI下给select设置默认选项) 例: $("select[name='result']").val(11); //重新渲染表单 ...

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

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

随机推荐

  1. cookie与session django中间件

    目录 一.什么是cookie 二.django中操作cookie 2.1 如何操作cookie 2.2 操作cookie 三.什么是session 四.django中操作session 4.1 创建c ...

  2. CouchDB学习-集群管理

    官方文档 集群管理 理论 在etc/fefault.ini文件中有以下部分: [cluster] q=8 n=3 q - 分片的数量 n - 每一份文档的拷贝数量(加上原文档一共几份副本) 创建数据库 ...

  3. c语言入门到精通怎么能少了这7本书籍?

    C语言作为学编程最好的入门语言,对一个初进程序大门的小白来说是很有帮助的,学习编程能培养一个人的逻辑思维,而C语言则是公认的最符合人们对程序的认知的一款计算机语言,很多大学都选择了使用C语言作为大学生 ...

  4. 【每天一题】LeetCode 0107. 自底向上层遍历二叉树

    开源地址:点击该链接 题目描述 * 给定一个二叉树,返回其节点值自底向上的层次遍历. * 即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历 * * 例如: * 给定二叉树 [3,9,20,nul ...

  5. C# List集合 GroupBy分组

    var grpBalance = listBalance.GroupBy(m => new { m.MerChantId, m.Name}).Distinct().Select(t => ...

  6. leaflet视频监控播放(附源码下载)

    前言 leaflet 入门开发系列环境知识点了解: leaflet api文档介绍,详细介绍 leaflet 每个类的函数以及属性等等 leaflet 在线例子 leaflet 插件,leaflet ...

  7. Sunset: Nightfall Vulnhub Walkthrough

    靶机链接: https://www.vulnhub.com/entry/sunset-nightfall,355/ 主机扫描: ╰─ nmap -p- -A 10.10.202.162Starting ...

  8. Android 基于ksoap2的webservice请求的学习

    [学习阶段] WebService网络请求? 其实我也是第一次遇到,之所以有这个需要是因为一些与 ERP 相关的业务,需要用到这样的一个请求方式. 开始学习WebService ①当然是百度搜索,这里 ...

  9. 集合系列 Map(十四):WeakedHashMap

    WeakedHashMap 也是 Map 集合的哈希实现,但其余 HashMap 的不同之处在于.其每个节点的 value 引用是弱引用,可以方便 GC 回收. public class WeakHa ...

  10. mysql如何处理高并发(转)

    mysql高并发的解决方法有:优化SQL语句,优化数据库字段,加缓存,分区表,读写分离以及垂直拆分,解耦模块,水平切分等. 高并发大多的瓶颈在后台,在存储mysql的正常的优化方案如下: (1)代码中 ...