Problem with TreeNode.BeginEdit()
I'm using WinForms TreeView开发者_如何学JAVA
and reaction to AfterLabelEdit
event. Here's the snippet of the code:
if (e.Label.Contains("|"))
{
if (WantAutofix())
{
label = e.Label.Replace('|', '_');
}
else
{
e.CancelEdit = true;
e.Node.BeginEdit();
return;
}
}
The problem is that when user doesn't want automatic fix of bad character, node doesn't stay in edit mode. Any way to fix this?
A few things to keep in mind:
- The
AfterLabelEdit
event always ends edit mode after it is raised, even if you callBeginEdit
in the middle of your event handler. You can useTreeView.BeginInvoke
to "leapfrog" this by having EditMode start up again after the TreeView does its thing. (NOTE: this does not create a new thread or race condition, it simply delays the method for 1 window message.) There is more information on some of the issues with this event here (though it suggests what I think is a worse solution). e.Label
isnull
if the user didn't make any changes, so when we "leapfrog" with BeginInvoke, it is as if the user didn't make any changes, so we also need to handle that case.- BeginInvoke is an acceptable workaround in this case, you should find it to be very reliable in this situation.
This works very well for me, tested with .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;
}
Use EndEdit and Replace the "bad character" if user want automatic fix
You could try making the BeginEdit() occur asynchronously:
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();
That way the CancelEdit is given a chance to complete before a new BeginEdit tries to take over.
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();
}
精彩评论