上次有寫過,
如果傳進來的 BindingSource 有 PositionChanged 的事件的時候就去觸發它!
請參閱【C# 如何強制驅動物件的事件?】。
這次不一樣的是,如果傳進來的 BarButtonItem 有 ItemClick 的事件的話,
我要將它移除,然後重新掛上自己的事件。
為什麼會有這樣的需求呢?
因為在底層的查詢按鈕直接將事件寫在 ItemClick 上面了,
而我想要拿這個按鈕來用卻又不想要執行底層的程式,
所以我需要將原來 delegate 的移除之後再重新掛上我的 ItemClick 程式。
緣由說明完畢啦!接下來就要實做了,
依照上次【C# 如何強制驅動物件的事件?】的做法居然得不到 FieldInfo !
google 了很久,後來在 DevExpress 的討論區裡面看到一個範例,
雖然是 VB 有點看不太懂,
後來我照著翻譯成 C# 之後也是可以跑的,
程式碼如下:
private void
ResetBarItemClickEvent(DevExpress.XtraBars.BarButtonItem
btn)
{
FieldInfo itemClickInfo = (typeof(DevExpress.XtraBars.BarItem)).GetField("itemClick",
BindingFlags.Static
| BindingFlags.NonPublic);
FieldInfo eventsInfo = (typeof(Component)).GetField("events",
BindingFlags.Instance
| BindingFlags.NonPublic);
/*
* 測試之後 itemClickInfo.GetValue(btn)
* 跟
itemClickInfo.GetValue(null) 得到的都一樣,
* 不知道差別是甚麼?
*/
object itemClick = itemClickInfo.GetValue(btn);
//object itemClick =
itemClickInfo.GetValue(null);
EventHandlerList events =
eventsInfo.GetValue(btn) as EventHandlerList;
if (events == null)
return;
ItemClickEventHandler handler =
events[itemClick] as ItemClickEventHandler;
Delegate d = events[itemClick];
if (d != null)
{
events.RemoveHandler(itemClick, d);
}
btn.ItemClick += new ItemClickEventHandler(btn_ItemClick);
}
重點說明如下:
由於 ItemClick 的事件是掛在 BarItem 下面的,所以必須由 BarItem 去 GetField ,
然後關鍵的 "itemClick" 也在 BarItem 下面。如下的程式碼與圖所示。
FieldInfo itemClickInfo = (typeof(DevExpress.XtraBars.BarItem)).GetField("itemClick",
BindingFlags.Static | BindingFlags.NonPublic);
用 FieldInfo.GetValue() 可以得到那個事件的物件指標。
object itemClick = itemClickInfo.GetValue(btn);
用下面兩行程式取得 EventHandlerList 。
FieldInfo eventsInfo = (typeof(Component)).GetField("events",
BindingFlags.Instance | BindingFlags.NonPublic);
EventHandlerList events = eventsInfo.GetValue(btn) as EventHandlerList;
最後用 itemClick 物件指標在 EventHandlerList 裡面去取得 ItemClick 的 delegate。
Delegate d = events[itemClick];
得到這個 delegate 之後我們就可以把它移除,
events.RemoveHandler(itemClick, d);
然後加上自己的程式了!
btn.ItemClick += new ItemClickEventHandler(btn_ItemClick);
收攤!
相關資料
How can I test if BarItem has click event associated with it and if doesn't disable the item
Location BarButtonItem of a PopupMenu
How do you use reflection to get the invocation list of an event delegate in a BarButtonItem?
C# 移除事件 <-這一篇寫得不錯,很值得參考!
不能override他嗎
回覆刪除就是不能丫!
回覆刪除用 += 的方式只能累加上去,
沒辦法 override 啊!