C# 排序后是否将滚动条重置到树状视图的顶部?

C# 排序后是否将滚动条重置到树状视图的顶部?,c#,.net,winforms,C#,.net,Winforms,我有一个相当大的树结构,每当用户添加或删除子节点时,树都会重新排序。这一切都很好,但我的问题是:排序后,滚动条会自动重置到树的顶部。我想让滚动条保持(或返回)刚刚添加或删除节点的位置,这样用户就不必每次添加或删除内容时都向下滚动并查找父节点 一段时间以来,我一直在想办法做到这一点,但运气不好。有人有什么建议吗 以下是我用于删除子节点的方法(如果有帮助): private void RemoveFromCategoryEvent(object sender, EventArgs e) { Su

我有一个相当大的树结构,每当用户添加或删除子节点时,树都会重新排序。这一切都很好,但我的问题是:排序后,滚动条会自动重置到树的顶部。我想让滚动条保持(或返回)刚刚添加或删除节点的位置,这样用户就不必每次添加或删除内容时都向下滚动并查找父节点

一段时间以来,我一直在想办法做到这一点,但运气不好。有人有什么建议吗

以下是我用于删除子节点的方法(如果有帮助):

private void RemoveFromCategoryEvent(object sender, EventArgs e)
{
  SuspendLayout();

  if (treeViewCategories.SelectedNode != null)
  {
    TreeNode treeNode = treeViewCategories.SelectedNode;
    TreeNode parentNode = treeNode.Parent;
    if ((settingGroup != null) && (settingGroup.GroupRootCategory != null)
        && (settingGroup.GroupRootCategory.Settings != null) && (treeNode.Tag is ISetting)
        && (parentNode.Tag is IDeviceSettingCategory))
    {
      ISetting currentSetting = treeNode.Tag as ISetting;
      (parentNode.Tag as IDeviceSettingCategory).Settings.Remove(currentSetting);
      treeNode.Remove();

      settingGroup.GroupRootCategory.Settings.Add(currentSetting);
      TreeNode settingNode = rootCategoryNode.Nodes.Add(currentSetting.ShortName);
      settingNode.Tag = currentSetting;

      settingNode.ImageIndex = Utilities.SettingCategoryChildImage;
      settingNode.SelectedImageIndex = Utilities.SettingCategoryChildImage;

      treeViewCategories.Sort(); //scrollbar reset happens here
    }
  }

  ResumeLayout();
}

您可以使用p/Invoke获取当前滚动位置,保存它,然后在排序后恢复它

您将需要以下API调用:

[DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
public static extern int GetScrollPos(int hWnd, int nBar);

[DllImport("user32.dll")]
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); 
}
获取当前位置:

[DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
public static extern int GetScrollPos(int hWnd, int nBar);

[DllImport("user32.dll")]
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); 
}
设置位置:

[DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
public static extern int GetScrollPos(int hWnd, int nBar);

[DllImport("user32.dll")]
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); 
}

回答得很好。这就成功了。非常感谢你,布拉德利!:)