前言

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

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. poj 2398 Toy Storage(计算几何)

    题目传送门:poj 2398 Toy Storage 题目大意:一个长方形的箱子,里面有一些隔板,每一个隔板都可以纵切这个箱子.隔板将这个箱子分成了一些隔间.向其中扔一些玩具,每个玩具有一个坐标,求有 ...

  2. poj 2631 Roads in the North (自由树的直径)

    Roads in the North Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4513   Accepted: 215 ...

  3. HttpRunner学习8--使用debugtalk.py辅助函数

    前言 在HttpRunner中,我们的测试用例都是写在 YAML/JSON 文件中,有时候我们想借助代码来实现某些较复杂的功能,但在 YAML/JSON 中是无法直接写代码来处理的,这个时候,我们可以 ...

  4. 【每天一题】LeetCode 0067. 二进制求和

    开源地址:https://github.com/jiauzhang/algorithms 题目描述 * https://leetcode-cn.com/problems/add-binary * 给定 ...

  5. vue组件初始化过程

    之前文章有写到vue构造函数的实例化过程,只是对vue实例做了个粗略的描述,并没有说明vue组件实例化的过程.本文主要对vue组件的实例化过程做一些简要的描述. 组件的实例化与vue构造函数的实例化, ...

  6. Java设计模式13:责任链模式

    前言 来菜鸟这个大家庭10个月了,总得来说比较融入了环境,同时在忙碌的工作中也深感技术积累不够,在优秀的人身边工作必须更加花时间去提升自己的技术能力.技术视野,所以开一个系列文章,标题就轻松一点叫做最 ...

  7. Android Studio中的AndroidManifest.xml文件分析

    一.关于AndroidManifest.xml AndroidManifest.xml清单文件是每个Android程序中必须的文件,它是整个Android程序的全局描述文件,除了能声明程序中的Acti ...

  8. Your activation code could not be validated (error 1653219)

    很多小伙伴私聊我反应说,完全按照了你的 idea 激活教程走的,可最后还是没能激活成功,提示错误信息为: Your activation code could not be validated (er ...

  9. 【BZOJ 2138】stone

    Problem Description 话说 \(Nan\) 在海边等人,预计还要等上 \(M\) 分钟.为了打发时间,他玩起了石子. \(Nan\) 搬来了 \(N\) 堆石子,编号为 \(1\) ...

  10. Analyze Data 分析数据

    In this lesson, you will learn how to add the Analysis functionality to your application. For this p ...