前言

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

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. ClassNotFoundException------IDEA下的一种原因

    由于直接复制文件而未经过IDE造成次异常,需要修改程序入口:

  2. Codeforces Round #592 (Div. 2)

    A. Pens and Pencils 题目链接:https://codeforces.com/contest/1244/problem/A 题意: 给定五个数 a , b , c , d , k 求 ...

  3. pip和conda添加国内清华镜像源(亲测有效)

    文章目录 pip和conda 添加国内清华镜像 1. pip源更改: 2. conda源更改: pip和conda 添加国内清华镜像 python模块安装,使用国内源可以提高下载速度. 1. pip源 ...

  4. ps命令输出进程状态S后面加号的含义

    最近发现一个问题,ps命令输出里面进程状态为S+的含义,网上好多文章都说是表明进程“位于在后台进程组”. 例如下面这个ps命令输出说明: D 不可中断 Uninterruptible sleep (u ...

  5. 脚本批量执行Redis命令

    1.将命令写在文件中 数据量比较大的话,建议用程序去生成文件.例如: List<String> planIdList = planDao.findAll().parallelStream( ...

  6. Django-如何写好一个celery定时任务

    1.首先在项目同名目录下建一个celery.py from __future__ import absolute_import import os from celery import Celery ...

  7. Java连载60-类之间的六种关系

    一.类之间的关系 1.泛化关系(UML图:实线空心三角形箭头,箭头指向被继承方) 类和类.接口与接口之间的继承称为泛化关系 public class A {} class B extends A{} ...

  8. Spark Streaming任务延迟监控及告警

    概述 StreamingListener 是针对spark streaming的各个阶段的事件监听机制. StreamingListener接口 //需要监听spark streaming中各个阶段的 ...

  9. 再窥R(包括一个R示例)

    一.将输出作为输入——结果的重用 R有个特点,分析的结果可以保存下来,并可以作为进一步分析的输入使用.下面我们通过R中的预先安装好的数据集作为实例(这里只讲述原理,涉及到的统计知识,以后在另外的统计专 ...

  10. 一个随机切换user_agent的第三方python库:my_fake_useragent

    因为my_fake_useragent 是第三方,所以需要自己进行安装. 不用担心,它没有任何依赖或者附加环境,只安装它自己就行. 方法1: pycharm传统安装方式. 方法2: pip insta ...