WPF TreeView 虚拟化-设置滚动到选中项

原文:WPF TreeView 虚拟化-设置滚动到选中项

前言

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

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

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

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

TreeView滚动定位

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

 1     static void OnIsScrolledToViewWhenSelectedChanged(
 2         DependencyObject depObj, DependencyPropertyChangedEventArgs e)
 3     {
 4         if (depObj is TreeViewItem treeViewItem && e.NewValue is bool isIntoViewWhenSelected)
 5         {
 6             treeViewItem.Loaded -= TreeViewItem_Loaded;
 7             if (isIntoViewWhenSelected)
 8             {
 9                 treeViewItem.Loaded += TreeViewItem_Loaded;
10             }
11         }
12     }

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

 1     static void TreeViewItem_Loaded(object sender, RoutedEventArgs e)
 2     {
 3         var treeViewItem = e.OriginalSource as TreeViewItem;
 4         if (treeViewItem != null)
 5         {
 6             treeViewItem.Loaded -= TreeViewItem_Loaded;
 7             if (treeViewItem.IsSelected)
 8             {
 9                 treeViewItem.BringIntoView();
10             }
11         }
12     }

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

虚拟化后的TreeView滚动定位

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

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

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

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

 1     static void OnIsScrolledToViewWhenSelectedChanged(
 2         DependencyObject depObj, DependencyPropertyChangedEventArgs e)
 3     {
 4         if (depObj is TreeViewItem treeViewItem && e.NewValue is bool isIntoViewWhenSelected)
 5         {
 6             treeViewItem.Loaded -= TreeViewItem_Loaded;
 7             //获取父控件TreeView
 8             var treeView = treeViewItem.FindVisualParent<TreeView>();
 9             if (isIntoViewWhenSelected)
10             {
11                 //开启了虚拟化且未完成滚动,直接返回
12                 var isOpeningVitualizing = ScrollViewer.GetCanContentScroll(treeView) && VirtualizingPanel.GetIsVirtualizing(treeView);
13                 if (isOpeningVitualizing && GetHasSetSelectedItemVisible(treeView))
14                 {
15                     return;
16                 }
17                 treeViewItem.Loaded += TreeViewItem_Loaded;
18             }
19         }
20     }

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

如果开启了虚拟化,

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

黑科技:

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

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

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

 1     static void TreeViewItem_Loaded(object sender, RoutedEventArgs e)
 2     {
 3         var treeViewItem = e.OriginalSource as TreeViewItem;
 4         if (treeViewItem != null)
 5         {
 6             treeViewItem.Loaded -= TreeViewItem_Loaded;
 7             //获取父控件TreeView
 8             var treeView = treeViewItem.FindVisualParent<TreeView>();
 9             //是否开启了虚拟化
10             var isOpeningVirtualizing = ScrollViewer.GetCanContentScroll(treeView) && VirtualizingPanel.GetIsVirtualizing(treeView);
11             if (isOpeningVirtualizing)
12             {
13                 if (treeViewItem.IsSelected)
14                 {
15                     //设置已完成滚动,减少剩余项的加载判断
16                     SetHasSetSelectedItemVisible(treeView, true);
17                     treeViewItem.BringIntoView();
18                 }
19                 else
20                 {
21                     treeViewItem.BringIntoView();
22                 }
23             }
24             else if(treeViewItem.IsSelected)
25             {
26                 treeViewItem.BringIntoView();
27             }
28         }
29     }

WPF 列表开启虚拟化的方式

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

原文地址:https://www.cnblogs.com/lonelyxmas/p/11015955.html

时间: 2024-10-16 11:26:20

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

根据值设置select的选中项

$('.selector').attr("checked", true); <s:iterator value="jobSelect" id="jobLink2"> <s:iterator value="jobLink2" id="job2"> var arr = $('.selector'); var a = ${job2.id}; $('.selector').each(func

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

public void SetSelectedListItem(ListBox lst, List<DBServerIPBind> source) { for (Int32 i = 0; i < source.Count; i++) { if (source[i].IsSelected) { ListItem item = lst.Items.FindByValue(source[i].DataValueField); if (!object.Equals(item,null)) { i

使用val()方法设置表单中的默认选中项

有时候我们展示给用户的表单中的checkbox,radio,selec等标签的一些项是默认选中的.比方:当用户改动文章的时候,假设相应的栏目为下拉框的话,那么它的默认选中值应该是原来的栏目位置. 能够使用jquery中的val()方法给select.checkbox.radio设置默认选中项. 对于multiple类型的select和checkbox还能够设置多个默认值. 效果图: 方法: $("select#multiple").val(["选择2号","

在WPF的MVVM框架中获取下拉选择列表中的选中项

文章概述: 本演示介绍如何在WPF的MVVM框架中,通过数据绑定的方式获取下拉列表中的选中项.程序运行后的效果如下图所示: 相关下载(代码.屏幕录像):http://pan.baidu.com/s/1sjwN357 在线播放:http://v.youku.com/v_show/id_XODA5OTYzMDU2.html 温馨提示:如果屏幕录像和代码不能正常下载,可站内留言,或发邮件到[email protected] XAML代码如下所示: <Window x:Class="Demo02E

Jquery设置select控件指定text的值为选中项

<select name="streetid" id="streetid"> <option value="4">北环路</option> <option value="5">天河路</option> <option value="6">清华园路</option> <option value="7"

Mutiselect下拉复选框(保存和设置默认选中项)

HTML代码 <asp:DropDownList ID="ddlWarehouseIds" runat="server" CssClass="ddl"></asp:DropDownList> <input type="hidden" name="<%#Eval("WarehouseNames")%>" id="hid_<%#Eva

Dev控件的下拉框控件设置默认选中项

DevExpress中下拉框控件comboBoxEdit,用法和winform的不太一样,在绑完选项后,希望设置默认选中项. 有2种方法: 方法1this.cmbMacScan.EditValue = new CheckedListBoxItem { Value = model.ScanInterval, Description = model.ScanInterval.ToString() }; this.cmbMacScan.RefreshEditValue(); 方法2this.cmbMa

C#遍历得到checkboxlist选中值和设置选中项

得到选中项的value值并拼接成一个字符串返回 public string GetChecked(CheckBoxList checkList, string separator) { string str = ""; for (int i = 0; i < checkList.Items.Count; i++) { if (checkList.Items[i].Selected) { str += checkList.Items[i].Value + separator; }

锁定菜单选中项(BS程序)

1  要求 在BS程序中通常都用需要显示当前选中菜单要求,具体要求如 高亮菜单.用特殊颜色标示等. 实现难点:因为html不保存状态,所以每次菜单的改变如何记录这个状态是问题的核心. 2 解决方法 我大致使用过以下几种方式. 1. iframe(比较古老的做法): 这种方法做法最为简单,就是把menu菜单.菜单导向的内容分别放置在两个页面中(内容使用 iframe ),这样就能简单的实现要求了,不过介于当前反iframe的风潮,目前也不推荐用使用此种方式. 2.在页面中设置菜单状态 因为在点击菜