我添加了一個事件處理程序到的UIElement:如何驗證事件處理程序已添加
element.AddHandler(Class.Event, handler, true);
但處理方法沒有被調用。我如何驗證處理程序已被正確添加?例如:
element.GetAssociatedHandlers();
謝謝!
我添加了一個事件處理程序到的UIElement:如何驗證事件處理程序已添加
element.AddHandler(Class.Event, handler, true);
但處理方法沒有被調用。我如何驗證處理程序已被正確添加?例如:
element.GetAssociatedHandlers();
謝謝!
如果您只是想在調試器中驗證添加了事件處理程序,則可以將該事件強制轉換爲System.Delegate
並查看調用列表。這可以在Visual Studio立即窗口中完成。在這裏,我檢查名爲「MyEvent」的事件,果然有3個處理程序的調用列表添加:
((System.Delegate)MyEvent).GetInvocationList()
{System.Delegate[3]}
[0]: {Method = {Void handler11_MessageReceived(System.Object, MyProject.MyEventArgs)}}
[1]: {Method = {Void handler21_MessageReceived(System.Object, MyProject.MyEventArgs)}}
[2]: {Method = {Void handler21_MessageReceived(System.Object, MyProject.MyEventArgs)}}
您還可以瀏覽在監視窗口調用列表。
例如,如果您不確定某些事件偵聽器是否已妥善處置,那麼執行此操作可能甚至會有用。
更新:如何以編程方式檢查一個事件是否包含另一個事件。
以編程方式檢查事件處理程序是否已添加到事件中比人們想象的要複雜得多,因爲事件實際上是MulticastDelegate的一種形式。多播委託可以是由(例如)delegate語句或lambda表達式創建的「原子」刪除,也可以是通過將兩個或多個多播委託相加而創建的組合委託。事實證明,當一個組合委託被添加到第二個組合中或從第二個組合中減去時,實際發生的是其調用列表被添加到另一個組合中或從其中減去。例如。
Action a =() => Console.WriteLine("a");
Action b =() => Console.WriteLine("b");
Action c =() => Console.WriteLine("c");
Action d =() => Console.WriteLine("d");
var ab = a + b;
var cd = c + d;
var ad = a + d;
var bc = b + c;
var abcd = ab + cd;
var adbc = ad + bc;
var abc = abcd - d;
var bcd = abcd - a;
bool test1 = (abcd == (a + b + c + d)); // returns true
bool test2 = abcd.GetInvocationList().Contains(a); // returns true;
bool test3 = abcd.GetInvocationList().Contains(ab); // returns **false**;
bool test4 = abc.GetInvocationList().Contains(d); // returns false
如果你想創建一個公共靜態擴展方法來檢查,看看你的處理程序是否被添加到一個事件,應該正確處理添加的多播委託的情況下。但是,這是否意味着該事件具有處理程序的所有代表?或者他們需要依次綁定在一起,因爲Delegate.Combine確實保持秩序?後者下面的擴展方法檢查:
public static class EventHelper
{
/// <summary>
/// Return true if all the atomic delegates in the multicast delegate handler are bound into the
/// publisher, grouped together and in the same order.
/// </summary>
/// <param name="publisher"></param>
/// <param name="handler"></param>
/// <returns></returns>
public static bool HasBound(this Delegate publisher, Delegate handler)
{
if (publisher == null || handler == null)
return false;
if (publisher == handler)
return true;
var publisherList = publisher.GetInvocationList();
var handlerList = handler.GetInvocationList();
return (publisherList.SublistIndex(handlerList, 0) >= 0);
}
public static bool HasBound<TEventArgs>(this EventHandler<TEventArgs> publisher, EventHandler<TEventArgs> handler) where TEventArgs : EventArgs
{
return HasBound((Delegate)publisher, (Delegate)handler);
}
public static bool HasBound(this EventHandler publisher, EventHandler handler)
{
return HasBound((Delegate)publisher, (Delegate)handler);
}
}
public static class ListHelper
{
public static int SublistIndex<T>(this IList<T> list, IList<T> sublist, int start)
{
var comparer = EqualityComparer<T>.Default;
for (int listIndex = start, end = list.Count - sublist.Count + 1; listIndex < end; listIndex++)
{
int count = 0;
while (count < sublist.Count && comparer.Equals(sublist[count], list[listIndex + count]))
count++;
if (count == sublist.Count)
return listIndex;
}
return -1;
}
}
這裏是測試結果:
bool test08 = a.HasBound(a); // returns true;
bool test09 = b.HasBound(a); // returns true;
bool test10 = abcd.HasBound(a + b + c + d); // returns true;
bool test11 = abcd.HasBound(adbc); // returns false - wrong order.
bool test12 = abcd.HasBound(a); // returns true;
bool test13 = cd.HasBound(a); // return false
bool test14 = bcd.HasBound(bc); // returns true despite the fact that bcd was not created directly from bc.
bool test15 = abcd.HasBound(ad); // returns false because the "ad" events are not adjacent in abcd.
老實說,我也不會做不過這個調試之外。實際上編碼檢查看看一個監聽器是否與事件綁定似乎是錯誤的。
更新2真正的問題在這裏如何從微軟UIElement獲取所有事件處理程序?它必須通過一些令人討厭的反思來完成,這種反思在將來的.Net版本中是不能保證的,如下所示:How to remove all Click event handlers?和這裏:How would it be possible to remove all event handlers of the 'Click' event of a 'Button'?。
不起作用。 '((System.Delegate)MouseWheel).GetInvocationList()'→'事件'System.Windows.Forms.Control.MouseWheel'只能出現在+ =或 - =' –
您可以獲取委託的調用列表來驗證您的處理程序是否已連接。
event Action MyEvent;
bool IsEventHandlerAdded()
{
foreach (Delegate existingHandler in this.MyEvent.GetInvocationList())
{
return existingHandler == MyEvent;
}
return false;
}
我認爲成功執行'element.AddHandler(Class.Event,handler,true);'應該足夠了。 – pushpraj
[獲取WPF控件的所有附加事件處理程序]的可能副本(http://stackoverflow.com/questions/16647388/getting-all-the-attached-event-handlers-for-a-wpf-control) –