首页 > 解决方案 > WinForms MultiSelectTreeView - EnsureVisible() 不工作

问题描述

删除一个 TreeNode 后,我希望视图位于我删除的那个节点之后(稍后也应该实现相同的功能来编辑节点),但目前它总是再次显示列表顶部,我需要向下滚动手动,这对用户来说可能非常烦人。

我正在使用 EnsureVisible() 方法,但不幸的是它不起作用(我正在使用包含大约 30 个没有子节点的节点的 TreeView 对其进行测试)。

该函数的代码(我认为只有第一行和最后 4/5 行是相关的):

public override void Remove()
    {
        TreeNode moveToThisNode = treeControl1.SelectedNodes.Last().NextVisibleNode;

        // first, group them by whether they are ObjectGroups or ObjectTypes
        var grouping = from node in treeControl1.SelectedNodes
                       where !node.IsUngroupedNode()
                       let isGroup = node.IsGroupNode()
                       group node by isGroup into g
                       select new { IsGroupNode = g.Key, Items = g };

        foreach (var grp in grouping)
        {
            foreach (var selectedNode in grp.Items)
            {
                // Only allow removal FIRSTLY of ObjectGroups and SECONDLY that are NOT the "ungrouped" group.
                if (grp.IsGroupNode)
                {
                    // Removes the Group
                    var cmd = (Commands.DataCommand<string>)mApplicationData.CommandFactory.Create(string.Concat(CommandPrefix, "Remove"));
                    cmd.Data = selectedNode.Text;
                    cmd.Execute();
                }
                else // ObjectType node --> just move to ungrouped
                {
                    var t = (ObjectType)selectedNode.Tag;
                    var parentNode = selectedNode.Parent;
                    if (parentNode?.IsGroupNode() == true &&
                        parentNode?.IsUngroupedNode() == false) // No removal of ObjectTypes from within "ungrouped"
                    {
                        var group = (ObjectGroup)parentNode.Tag;
                        // Remove the ObjectType from the ObjectGroup but does not delete it -> becomes "ungrouped".
                        var cmd = (Commands.IGroupTypeCommand)mApplicationData.CommandFactory.Create(string.Concat(CommandPrefix, "TypeRemove"));
                        cmd.ObjectClass = t.Class;
                        cmd.ObjectTypeName = t.Name;
                        cmd.Data = group.Name;
                        cmd.Execute();
                    }
                }
            }
        }
        UpdateData();

        if (moveToThisNode!=null)
        {
            moveToThisNode.EnsureVisible();
            MessageBox.Show("Dummy test if moveToThisNode isn't null");
        }
    }

标签: c#winformstreeview

解决方案


我想到了!

问题是在 Remove() 函数之后,我的 UpdateData() 函数被调用,它重绘所有节点。所以在此之前调用 EnsureVisible() 完全是胡说八道。

所以我所做的是,在 Remove() 中,我将要跳转到的节点的名称存储在成员变量中,并在 UpdateData() 结束时,我从 TreeNodeCollection 和(最终)中获取具有该名称的节点为它调用 EnsureVisible()。


推荐阅读