Проблема с TreeNode.Метод beginedit()
Я использую WinForms TreeView и реакция на AfterLabelEdit событие. Вот фрагмент кода:
if (e.Label.Contains("|"))
{
if (WantAutofix())
{
label = e.Label.Replace('|', '_');
}
else
{
e.CancelEdit = true;
e.Node.BeginEdit();
return;
}
}
проблема в том, что когда пользователь не хочет автоматического исправления плохого символа, узел не остается в режиме редактирования. Как это исправить?
4 ответов
несколько вещей, чтобы иметь в виду:
- на
AfterLabelEditсобытие всегда завершает режим редактирования после его возникновения, даже если вы вызываетеBeginEditв середине обработчика событий. Вы можете использоватьTreeView.BeginInvokeчтобы "перепрыгнуть" это, запустив EditMode снова после того, как TreeView сделает свое дело. (Примечание: это не создает новый поток или состояние гонки, он просто задерживает метод для 1 сообщения окна.) есть дополнительная информация о некоторых проблемах с этим событием здесь (хотя он предполагает, что я думаю, что это худшее решение). -
e.Labelisnullесли пользователь не внес никаких изменений, поэтому, когда мы "прыгаем" с 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;
}
вы можете попробовать сделать 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();
таким образом, CancelEdit получает шанс завершить, прежде чем новый BeginEdit попытается взять на себя.
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();
}