2009-03-18 37 views
25

Tôi có một biểu mẫu WinForms sẽ không đóng. Trong OnFormClosing, e.Cancel được đặt thành true. Tôi đoán rằng một số đối tượng trong ứng dụng của tôi đã ràng buộc với sự kiện Đóng hoặc FormClosing, và đang chặn đóng. Để tìm hiểu, tôi muốn xác định những đại biểu nào bị ràng buộc vào một trong những sự kiện này.Xác định danh sách các trình xử lý sự kiện được liên kết với sự kiện

Có cách nào để xác định danh sách các trình xử lý được liên kết với một sự kiện không? Lý tưởng nhất là tôi sẽ làm điều này thông qua trình gỡ rối Visual Studio, nhưng có thể viết mã trong ứng dụng để tìm trình xử lý nếu cần. Hiểu rằng một sự kiện giống như một trường riêng ẩn, tôi đã điều hướng thông qua Trình gỡ lỗi đến "Các trường không công khai" cho tổ tiên "Windows.Forms.Form" của biểu mẫu của tôi, nhưng không có kết quả.

Trả lời

29

Nói tóm lại, bạn không có nghĩa là để làm điều này - nhưng đối với mục đích gỡ lỗi ...

Một sự kiện là thường được hỗ trợ bởi một lĩnh vực riêng - nhưng không phải với điều khiển; họ sử dụng phương pháp EventHandlerList. Bạn sẽ phải truy cập vào thành viên được bảo vệ của biểu mẫu Events, tìm đối tượng được ánh xạ tới đối tượng EVENT_FORMCLOSING (riêng tư).

Khi bạn có FormClosingEventHandler, GetInvocationList sẽ thực hiện công việc.


using System; 
using System.ComponentModel; 
using System.Reflection; 
using System.Windows.Forms; 
class MyForm : Form 
{ 
    public MyForm() 
    { // assume we don't know this... 
     Name = "My Form"; 
     FormClosing += Foo; 
     FormClosing += Bar; 
    } 

    void Foo(object sender, FormClosingEventArgs e) { } 
    void Bar(object sender, FormClosingEventArgs e) { } 

    static void Main() 
    { 
     Form form = new MyForm(); 
     EventHandlerList events = (EventHandlerList)typeof(Component) 
      .GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance) 
      .GetValue(form, null); 
     object key = typeof(Form) 
      .GetField("EVENT_FORMCLOSING", BindingFlags.NonPublic | BindingFlags.Static) 
      .GetValue(null); 

     Delegate handlers = events[key]; 
     foreach (Delegate handler in handlers.GetInvocationList()) 
     { 
      MethodInfo method = handler.Method; 
      string name = handler.Target == null ? "" : handler.Target.ToString(); 
      if (handler.Target is Control) name = ((Control)handler.Target).Name; 
      Console.WriteLine(name + "; " + method.DeclaringType.Name + "." + method.Name); 
     } 
    } 
} 
+0

Độ lạnh. Cảm ơn vì phản ứng nhanh, Marc! – JoshL

+0

Tôi đã đào bới xung quanh trong Reflector ngày khác tìm chính xác điều này tương tự. –

+1

Tôi có cùng nhu cầu; trong 'Control', các khóa xác định được đặt tên theo kiểu thời trang như' EventMouseDown' thay vì 'EVENT_MOUSEDOWN' vì chúng là' Form'. –

1

Vấn đề có thể là hình thức không xác nhận.

Sự kiện FormClosing được nuôi dưỡng bởi các WmClose phương pháp tư nhân trong Form, mà khởi e.Cancel-!Validate(true). Tôi đã không điều tra, nhưng trong một số trường hợp, Validate sẽ luôn trả lại false, khiến cho việc đóng bị hủy bất kể mọi trình xử lý sự kiện.

Để điều tra này, cho phép .Net source debugging, đặt một breakpoint trong handler FormClosing bạn, hãy vào các nguồn cho Form.WmClose (lên các cuộc gọi stack), đặt một breakpoint vào đầu WmClose, và đóng biểu mẫu một lần nữa. Sau đó, bước qua nó trong trình gỡ rối và xem lý do tại sao Validate đang trả lại false. (Hoặc trình xử lý sự kiện nào đang đặt e.Cancel thành đúng)

Để giải quyết vấn đề, hãy đặt e.Cancel thành false trong trình xử lý của riêng bạn.

Các vấn đề liên quan