Поддерживать положение прокрутки дерева
Как я могу сохранить позицию прокрутки элемента управления treeview в приложении .NET? Например, у меня есть управление древовидной структурой и вы можете пройти процесс добавления различных узлов к ним, привязывая их к нижней части. Во время этого процесса я могу просматривать дерево и просматривать разные узлы. Проблема заключается в том, когда процесс завершается, древовидное свиток прокручивается до самого низа.
Похоже, что вызов treenode.Expand() - это то, что меня отталкивает отсюда. Когда родительский node расширяется, он получает фокус.
Есть ли способ обойти это? Если я смотрю на конкретный node, пока процесс выполняется, я не хочу, чтобы он прыгал на меня, когда процесс завершен.
Ответы
Ответ 1
Я думаю, что понял:
- Получить node в верхней части дерева.
- Разверните родительский node.
- Сделайте node, который ранее был сверху.
If treeNodeParent.IsExpanded = False Then
Dim currentNode As TreeNode = TreeViewHosts.GetNodeAt(0, 0)
treeNodeParent.Expand()
currentNode.EnsureVisible()
End If
Это лучший способ сделать это?
Ответ 2
Я не парень VB, но в С# я делаю так:
Некоторые собственные функции Win32:
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int GetScrollPos(IntPtr hWnd, int nBar);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);
private const int SB_HORZ = 0x0;
private const int SB_VERT = 0x1;
Метод, который возвращает точку для текущей позиции прокрутки:
private Point GetTreeViewScrollPos(TreeView treeView)
{
return new Point(
GetScrollPos((int)treeView.Handle, SB_HORZ),
GetScrollPos((int)treeView.Handle, SB_VERT));
}
Способ установки положения прокрутки:
private void SetTreeViewScrollPos(TreeView treeView, Point scrollPosition)
{
SetScrollPos((IntPtr)treeView.Handle, SB_HORZ, scrollPosition.X, true);
SetScrollPos((IntPtr)treeView.Handle, SB_VERT, scrollPosition.Y, true);
}
Затем, когда вы обновляете свое дерево, сделайте следующее:
Point ScrollPos = GetTreeViewScrollPos(treeMain);
// write your update code here
SetTreeViewScrollPos(treeMain, ScrollPos);
Ответ 3
Другим способом сохранения позиции прокрутки без внешних функций является использование свойства TopNode дерева...
TopNode получает или устанавливает первое полностью видимое дерево node в элементе управления деревом.
Если вы просто хотите развернуть node и сохраните верхний node:
TreeNode topNode = m_Tree.TopNode;
treenode.Expand();
m_Tree.TopNode = topNode;
В противном случае, если вы перестраиваете дерево (например, обновляете структуру файла), вы можете использовать следующий метод...
Перед очисткой дерева сохраните полный путь до вершины node:
string topNodePath = null;
TreeNode topNode = null;
if (m_Tree.TopNode != null)
{
topNodePath = m_Tree.TopNode.FullPath;
}
m_Tree.Clear();
После добавления узлов проверьте его FullPath на topNodePath:
nodes.Add(node)
if ((topNodePath != null) && (node.FullPath == topNodePath))
{
topNode = node;
}
После добавления всех узлов обновите свойство TopNode дерева:
if (topNode != null)
{
m_Tree.TopNode = topNode;
}
Я использую подобный метод для выбранных и расширенных узлов.
SelectedNode работает почти точно как TopNode, показанный выше.
Для расширенных узлов я использую рекурсивную функцию для петли через дочерние узлы и добавляю путь расширенных узлов к списку. Затем расширяет их на основе их пути после добавления детей.
Конечно, если у вас много узлов-сестер с тем же именем, это может не сработать: -)
Ответ 4
Мне было удобно обернуть SetTreeViewScrollPosition(point)
с помощью BeginUpdate
и EndUpdate
...
private void treeViewXml1_Scroll(object sender, ScrollEventArgs e)
{
Point point = treeViewXml1.GetTreeViewScrollPosition();
treeViewXml2.BeginUpdate();
treeViewXml2.SetTreeViewScrollPosition(point);
treeViewXml2.EndUpdate();
}
private void treeViewXml2_Scroll(object sender, ScrollEventArgs e)
{
Point point = treeViewXml2.GetTreeViewScrollPosition();
treeViewXml1.BeginUpdate();
treeViewXml1.SetTreeViewScrollPosition(point);
treeViewXml1.EndUpdate();
}
Ответ 5
У меня также была та же проблема, когда сам свиток обновлялся, но содержимое древовидной структуры не прокручивалось. Это было легко зафиксировано добавлением BeginUpdate()
и EndUpdate()
вокруг SetScrollPos()
.
this.hierarchyTreeView.BeginUpdate();
SetScrollPos(this.hierarchyTreeView.Handle, SB_VERT, 5, true);
this.hierarchyTreeView.EndUpdate();
Ответ 6
myTreeView.Nodes[0].EnsureVisible();
Ответ 7
Это ревизия прекрасного ответа от Стефана Коэлла, как TreeViewExtension:
(полное решение)
using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interop;
using System.Windows.Media;
public static class TreeViewExtension
{
#region Constants
private const int ScrollBarHorizontal = 0x0;
private const int ScrollBarVertical = 0x1;
#endregion
#region Public Methods and Operators
[DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
public static extern int GetScrollPos(int hWnd, int nBar);
public static Point ScrollPosition(this TreeView treeView)
{
return new Point(
GetScrollPos((int)treeView.Handle(), ScrollBarHorizontal),
GetScrollPos((int)treeView.Handle(), ScrollBarVertical));
}
public static void ScrollTo(this TreeView treeView, Point scrollPosition)
{
SetScrollPos(treeView.Handle(), ScrollBarHorizontal, (int)scrollPosition.X, true);
SetScrollPos(treeView.Handle(), ScrollBarVertical, (int)scrollPosition.Y, true);
}
[DllImport("user32.dll")]
public static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);
#endregion
#region Methods
private static IntPtr Handle(this Visual treeView)
{
var handle = IntPtr.Zero;
var hwndSource = PresentationSource.FromVisual(treeView) as HwndSource;
if (hwndSource != null)
{
handle = hwndSource.Handle;
}
return handle;
}
#endregion
}
Возможно, это упрощает вашу работу; -)
Ответ 8
Лучше всего использовать UpdatePanel и вставлять в него теги treeview. Например,
<asp:UpdatePanel id="UpdatePanel">
<ContentTemplate>
<asp:TreeView id="TreeView">
</asp:TreeView>
</ContentTemplate>
</asp:UpdatePanel>
Это сработало для меня, и я надеюсь, что он решает вашу проблему.