C# TreeNode.BeginEdit()的问题

C# TreeNode.BeginEdit()的问题,c#,.net,winforms,treeview,treenode,C#,.net,Winforms,Treeview,Treenode,我正在使用WinFormsTreeView和对AfterLabelEdit事件的反应。以下是代码片段: if (e.Label.Contains("|")) { if (WantAutofix()) { label = e.Label.Replace('|', '_'); } else { e.CancelEdit = true; e.Node.BeginEdit(); return; } } 问题是,当用户不希望自动修复坏字符时,节点不

我正在使用WinForms
TreeView
和对
AfterLabelEdit
事件的反应。以下是代码片段:

if (e.Label.Contains("|"))
{
  if (WantAutofix())
  {
    label = e.Label.Replace('|', '_');
  }
  else
  {
    e.CancelEdit = true;
    e.Node.BeginEdit();
    return;
  }
}

问题是,当用户不希望自动修复坏字符时,节点不会保持在编辑模式。有没有办法解决这个问题?

您可以尝试使BeginEdit()异步发生:

private void treeView1_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
    {
        if (e.Label.Contains("|"))
        {
            if (WantAutofix())
            {
            }
            else
            {
                e.CancelEdit = true;
                BeginInvoke(new ActionDelegate(new NodeBeginEditAsync(e.Node).Execute));
                return;
            }
        }
    }
public class NodeBeginEditAsync
{
    private readonly TreeNode _node;

    public NodeBeginEditAsync(TreeNode node)
    {
        _node = node;
    }

    public void Execute()
    {
        _node.BeginEdit();
    }
}

public delegate void ActionDelegate();

这样,取消编辑就有机会在新的BeginEdit试图接管之前完成。

如果用户想要自动修复,请使用EndEdit并替换“坏字符”

需要记住的几点:

try this...    
TreeNode node = tv.SelectedNode;
                    if (tv.SelectedNode.Parent == null)
                    {
                        node.TreeView.LabelEdit = false;
                    }
                    else
                    {
                        node.Text = FieldName.Text;
                        if (node == null) { return; }
                        node.TreeView.LabelEdit = true;
                        node.BeginEdit();
                    }
<>代码>后LabelEdg> 事件在它被提升后结束编辑模式,即使在事件处理程序的中间调用<代码>初学者> /代码>。您可以使用
TreeView.BeginInvoke
通过在TreeView完成其任务后再次启动EditMode来“跳转”。(注意:这不会创建新的线程或争用条件,它只是延迟了1个窗口消息的方法。)关于此事件的一些问题有更多信息(尽管它表明了我认为更糟糕的解决方案)
  • e.Label
    null
    如果用户没有做任何更改,那么当我们使用BeginInvoke“跳转”时,就好像用户没有做任何更改,因此我们也需要处理这种情况
  • 在这种情况下,BeginInvoke是一种可接受的解决方法,您应该发现它在这种情况下非常可靠
  • 这对我来说非常有效,使用.NET 2.0进行了测试:

        private void treeView1_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
        {
            //we have to handle both the first and future edits
            if ((e.Label != null && e.Label.Contains("|") || (e.Label == null && e.Node.Text.Contains("|"))))
            {
                if (WantAutofix())
                {
                    e.CancelEdit = true;
    
                    if(e.Label != null)
                        e.Node.Text = e.Label.Replace('|', '_');
                    else
                        e.Node.Text = e.Node.Text.Replace('|', '_');
                }
                else
                {
                    //lets the treeview finish up its OnAfterLabelEdit method
                    treeView1.BeginInvoke(new MethodInvoker(delegate() { e.Node.BeginEdit(); }));
                }
            }
    
        }
    
        private bool WantAutofix()
        {
            return MessageBox.Show("You entered a |, you want me to AutoFix?", String.Empty, MessageBoxButtons.YesNo) == DialogResult.Yes;
        }
    

    不是一个真正的选择:我使用.NET2.0,这不是一个可靠的解决方案。你为什么这么认为?(您可能无法使用Action()语法,但BeginInvoke确实只能在.NET 2.0中工作)很简单。如果这个解决方案可行,那么我们就有一个竞争条件——线程在CancelEdit之前创建并运行——坏,在它之后——好。我不相信这是真的。这里的BeginInvoke是Control.BeginInvoke,它将消息发回UI线程以执行委托。因此,它相对于当前调用堆栈是“异步”的,但保证在UI线程上的当前堆栈完全展开后执行;不要理解我。如果他想自己修复的话,我想保持编辑模式。这就是问题所在。