• WPF Treeview控件开虚拟化后定位节点


     不开虚拟化,可以用下面的方法直接定位

    1. <Window x:Class="WpfApplication2.MainWindow"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. Title="MainWindow" Height="350" Width="525">
    5. <Grid>
    6. <TreeView Name="myTreeView">
    7. <TreeView.ItemTemplate>
    8. <HierarchicalDataTemplate ItemsSource="{Binding Children}">
    9. <TextBlock Text="{Binding Name}" />
    10. HierarchicalDataTemplate>
    11. TreeView.ItemTemplate>
    12. TreeView>
    13. Grid>
    14. Window>
    1. public partial class MainWindow : Window
    2. {
    3. public MainWindow()
    4. {
    5. InitializeComponent();
    6. // 示例数据
    7. var root = new TreeNode { Name = "Root" };
    8. for (int i = 0; i < 1000; i++)
    9. {
    10. var child = new TreeNode { Name = "Child " + i };
    11. for (int j = 0; j < 10; j++)
    12. {
    13. child.Children.Add(new TreeNode { Name = "SubChild " + j });
    14. }
    15. root.Children.Add(child);
    16. }
    17. myTreeView.ItemsSource = new ObservableCollection { root };
    18. // 等待数据绑定完成后选中并定位到指定节点
    19. this.Loaded += (s, e) => {
    20. var nodeToSelect = root.Children[51].Children[5]; // 举例:选中第51个Child的第6个SubChild
    21. SelectAndScrollToNode(myTreeView, nodeToSelect);
    22. };
    23. }
    24. private void SelectAndScrollToNode(TreeView treeView, TreeNode targetNode)
    25. {
    26. // 展开到目标节点
    27. ExpandAndSelect(treeView, targetNode);
    28. }
    29. public static IEnumerable<T> FindLogicalChildren<T>(DependencyObject obj) where T : DependencyObject
    30. {
    31. if (obj != null)
    32. {
    33. if (obj is T)
    34. yield return obj as T;
    35. foreach (DependencyObject child in LogicalTreeHelper.GetChildren(obj).OfType())
    36. foreach (T c in FindLogicalChildren<T>(child))
    37. yield return c;
    38. }
    39. }
    40. private void ExpandAndSelect(TreeView treeView, TreeNode targetNode)
    41. {
    42. foreach (var node in (ObservableCollection)treeView.ItemsSource)
    43. {
    44. if (ExpandAndSelectInternal(treeView, node, targetNode))
    45. break;
    46. }
    47. }
    48. private bool ExpandAndSelectInternal(ItemsControl parent, TreeNode currentNode, TreeNode targetNode)
    49. {
    50. if (currentNode == targetNode)
    51. {
    52. if (parent.ItemContainerGenerator.ContainerFromItem(currentNode) is TreeViewItem )
    53. {
    54. var currentItem = parent.ItemContainerGenerator.ContainerFromItem(currentNode) as TreeViewItem;
    55. currentItem.IsSelected = true;
    56. currentItem.BringIntoView();
    57. return true;
    58. }
    59. }
    60. if (parent.ItemContainerGenerator.ContainerFromItem(currentNode) is TreeViewItem)
    61. {
    62. var item = parent.ItemContainerGenerator.ContainerFromItem(currentNode) as TreeViewItem;
    63. item.IsExpanded = true;
    64. item.UpdateLayout();
    65. foreach (var childNode in currentNode.Children)
    66. {
    67. if (ExpandAndSelectInternal(item, childNode, targetNode))
    68. {
    69. item.IsExpanded = true;
    70. item.UpdateLayout();
    71. if (item.ItemContainerGenerator.ContainerFromItem(targetNode) is TreeViewItem )
    72. {
    73. var targetItem = item.ItemContainerGenerator.ContainerFromItem(targetNode) as TreeViewItem;
    74. targetItem.IsSelected = true;
    75. targetItem.BringIntoView();
    76. }
    77. return true;
    78. }
    79. }
    80. }
    81. return false;
    82. }
    83. }
    84. public class TreeNode
    85. {
    86. public TreeNode()
    87. {
    88. Children = new ObservableCollection();
    89. }
    90. public string Name { get; set; }
    91. public ObservableCollection Children { get; set; }
    92. }

    但是如果开了虚拟化,需要默认显示的节点很可能不在可视化树上,所以这套方法就不能用了。

    解决办法:计算默认选中项的垂直位置,直接操作滚动条移动到目标节点。

    1. private void SelectAndScrollToNode(TreeView treeView, TreeNode targetNode)
    2. {
    3. // 展开到目标节点
    4. ExpandAndSelect(treeView, targetNode);
    5. //根据targetNode计算滚动条的位置,这里就直接取中间位置了
    6. TreeViewAutomationPeer lvap = new TreeViewAutomationPeer(treeView);
    7. var svap = lvap.GetPattern(PatternInterface.Scroll) as ScrollViewerAutomationPeer;
    8. var scroll = svap.Owner as ScrollViewer;
    9. double hight = scroll.ScrollableHeight;
    10. scroll.ScrollToVerticalOffset(hight / 2);
    11. }

  • 相关阅读:
    Unity中Shader反射环境
    uniapp实现防抖搜索
    GStreamer概述
    前后端分离的增删改查步骤
    语音增强——谱减法的改进(过减法)及其python实现
    【Tomcat目录详解】关于Tomcat你还需要了解的详细内容
    Spring-Cloud-Openfeign如何支持数据压缩?
    Android A13 CTS 测试问题部分总结
    嵌入式Linux裸机开发(四)IMX6U主频和时钟配置
    spring事件监听与发布
  • 原文地址:https://blog.csdn.net/wangyue4/article/details/139461646