2011-07-06 22 views
6

Tôi đang sử dụng WinForms TreeView và phản hồi sự kiện AfterLabelEdit. Đây là đoạn mã:Sự cố với TreeNode.BeginEdit()

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

Vấn đề là khi người dùng không muốn sửa lỗi tự động của ký tự xấu, nút không ở chế độ chỉnh sửa. Có cách nào để sửa lỗi này không?

Trả lời

2

Một số điều cần lưu ý:

  1. Sự kiện AfterLabelEdit luôn kết thúc chế độ chỉnh sửa sau khi nó được nâng lên , ngay cả khi bạn gọi BeginEdit ở giữa trình xử lý sự kiện của bạn. Bạn có thể sử dụng TreeView.BeginInvoke để "leapfrog" điều này bằng cách có EditMode khởi động lại sau khi TreeView làm điều đó. (LƯU Ý: điều này không tạo ra một chủ đề hoặc điều kiện chủng tộc mới, nó chỉ đơn giản là trì hoãn phương pháp cho 1 thông báo cửa sổ.) Có thêm thông tin về một số sự cố với sự kiện này here (mặc dù nó cho thấy điều tôi nghĩ là tồi tệ hơn dung dịch).
  2. e.Labelnull nếu người dùng không thực hiện bất kỳ thay đổi nào, vì vậy khi chúng tôi "nhảy vọt" bằng BeginInvoke, dường như người dùng không thực hiện bất kỳ thay đổi nào, vì vậy chúng tôi cũng cần xử lý trường hợp đó.
  3. BeginInvoke là giải pháp có thể chấp nhận được trong trường hợp này, bạn sẽ thấy nó rất đáng tin cậy trong trường hợp này.

này hoạt động rất tốt đối với tôi, thử nghiệm với .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; 
    } 
0

Bạn có thể thử làm cho BeginEdit() xảy ra không đồng bộ:

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(); 

Bằng cách đó các CancelEdit được trao một cơ hội để hoàn thành trước khi một BeginEdit mới cố gắng để tiếp nhận.

+0

Không thực sự là một lựa chọn: Tôi sử dụng .NET 2.0, và điều này là không giải pháp đáng tin cậy. – Migol

+0

Tại sao bạn nghĩ vậy? (Bạn không thể sử dụng cú pháp Action() có lẽ, nhưng BeginInvoke certinly hoạt động trong .NET 2.0) – jlew

+0

Đơn giản. Nếu giải pháp này sẽ hoạt động thì chúng ta có điều kiện chủng tộc - luồng được tạo và chạy trước CancelEdit - BAD, sau nó - GOOD. – Migol

0

Sử dụng EndEdit và Thay thế "nhân vật xấu" nếu người dùng muốn sửa chữa tự động

+0

Bạn không hiểu chúng tôi. Tôi muốn ở lại trong chế độ chỉnh sửa nếu anh ấy muốn sửa chữa nó. Có vấn đề. – Migol

0
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(); 
        }