前言

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

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. CCF-CSP题解 201709-3 JSON查询

    要求写一个小程序完成JSON查询的功能. 查询dfs就好了. 存储JSON对象用图(树)就好,把\(<key[],type,val[]>\)作为节点,然后又是字符串处理了. 其实就是个简化 ...

  2. poj 1270 Following Orders (拓扑排序+回溯)

    Following Orders Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5473   Accepted: 2239 ...

  3. 线程中put(None)和主函数中put(None)的区别和用法

    ''' 初试生产者消费者模型代码 分析: 对象含有生产者.队列.消费者 Queue队列模块,不适合传大文件,通常传一些消息. ''' '''多生产者进程和多消费者进程''' #导入模块 from mu ...

  4. 《Dotnet9》系列-开源C# WPF控件库1《MaterialDesignInXAML》强力推荐

    时间如流水,只能流去不流回! 点赞再看,养成习惯,这是您给我创作的动力! 本文 Dotnet9 https://dotnet9.com 已收录,站长乐于分享dotnet相关技术,比如Winform.W ...

  5. Python工作好找吗?没有工作经验和学历怎么找?【就业必学】

    大家都知道,随着人工智能时代的到来,Python的需求也变的越来越大了.从目前各大IT招聘网上显示招聘需求是非常大,而且薪资基本都在10k起,高的可达40-50k,当然这个要求很高,看下普遍的吧: 一 ...

  6. conda docker镜像

    之前的python环境,使用ubuntu安装pip来安装python依赖,但是遇到缺少某些库的版本,比如一个项目需要用到faiss,pip只有最新的1.5.3版本,但是这个版本使用了较新的CPU指令, ...

  7. js简单动画:匀速动画、缓动动画、多物体动画以及透明度动画

    主要实现以下几种简单的动画效果(其实原理基本相同): 1.匀速动画:物体的速度固定 2.缓动动画:物体速度逐渐变慢 3.多物体动画 4.透明度动画 效果实现: 1.匀速动画(以物体左右匀速运动为例) ...

  8. AI: Web: 2 Vulnhub Walkthrough

    靶机下载链接: https://www.vulnhub.com/entry/ai-web-2,357 主机端口扫描: 尝试SQL注入,未发现有注入漏洞,就注册创建于一账户 http://10.10.2 ...

  9. Oracle trunc函数的使用

    1. 对日期的操作 2. 对数字的操作 1.对日期的操作 /**************日期********************/ SELECT TRUNC(SYSDATE) FROM DUAL; ...

  10. 通过 loganalyzer 展示数据库中的系统日志

    目录 通过 loganalyzer 展示数据库中的日志 环境准备 准备服务器: 日志服务器: 数据库服务器: 测试日志服务器和数据库是否连接: websrv服务器端: 通过 loganalyzer 展 ...