Подтвердить что ты не робот

Поддерживать положение прокрутки дерева

Как я могу сохранить позицию прокрутки элемента управления treeview в приложении .NET? Например, у меня есть управление древовидной структурой и вы можете пройти процесс добавления различных узлов к ним, привязывая их к нижней части. Во время этого процесса я могу просматривать дерево и просматривать разные узлы. Проблема заключается в том, когда процесс завершается, древовидное свиток прокручивается до самого низа.

Похоже, что вызов treenode.Expand() - это то, что меня отталкивает отсюда. Когда родительский node расширяется, он получает фокус.

Есть ли способ обойти это? Если я смотрю на конкретный node, пока процесс выполняется, я не хочу, чтобы он прыгал на меня, когда процесс завершен.

4b9b3361

Ответ 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>

Это сработало для меня, и я надеюсь, что он решает вашу проблему.