2011年8月29日 星期一

C# 如何強制驅動物件的事件?

我之前寫了一個通用的設定函數,
簡單的說呢,就是傳進去一個 BindingSource 與按鈕,
當按下按鈕的時候會依照條件去對 BindingSource 做 Filter,
然後 Filter 完了之後我想要執行 BindingSource.PositionChanged 的事件;
如果說這是在同一個 cs 的話很好處理,
但是就像我第一句所說的,我是要寫一個通用函數,
所以不在同一個 cs ,所以我沒有辦法直接呼叫 BindingSource.PositionChanged 的事件,
然後我也不確定傳進來的 BindingSource 是不是有 PositionChanged 的事件。
那我要怎麼樣知道傳進來的 BindingSource 有沒有 PositionChanged 的事件呢?
如果有 PositionChanged 的事件,那我又要怎麼樣去執行呢?
就這樣,花了我兩天的時間上網 google ,
到處找、到處 try!
發現網路上問這樣的問題的人很多,
但是我卻沒有找到解答,
最後我從大家片段的回答中 try 出來了!
現在就跟大家來分享吧!


最後的程式碼如下:



首先我們先從 BindingSource 的類別取得 Events 這個屬性,
(typeof(BindingSource)).GetProperty("Events".....
後面的 BindingFlags 是指定我們要取得甚麼樣的屬性的屬性(好繞口丫),
這樣得到的 propertyInfo 其實是一個 EventHandlerList 的物件,
然後我們要取得傳進來的 bs 的 EventHandlerList 的值,
propertyInfo.GetValue(bs, null),其中第二個參數在說明中有說
【索引屬性的選擇性索引值。非索引屬性的這個值應為 null。】
也就是說我們用 (EventHandlerList)propertyInfo.GetValue(bs, null) 去取得 bs 的所有事件。
我們可以看到 EventHandlerList 的內容值就是我們在 Designer.cs 裡面的 PositionChanged 事件,
如下圖所示,可以看到一個 On_FilterPositionChanged 的事件!





這個跟我們在 Designer.cs 裡面的宣告是一樣的,
this.bsFilter.PositionChanged += new System.EventHandler(this.On_FilterPositionChanged);
所以可以說我們已經抓到了傳進來的這個 bs 它的事件;
接下來我們用 bs.GetType().GetField("EVENT_POSITIONCHANGED"....
去取得 "EVENT_POSITIONCHANGED" 這個欄位的值,
然後我們用 eventHandlerList[fieldInfo.GetValue(null)] 去取得這個 Delegate,
最後我們就可以用 d.Method.Invoke 去執行我們原來在 Form 上面的 On_FilterPositionChanged
真是繞了一大圈丫!
搞得我自己也很模糊!


然後我又試了一下是否可以抓到其他的事件,
所以我又新增了 BindingSource 的另一個事件,
this.bsFilter.ListChanged += new System.ComponentModel.ListChangedEventHandler(this.bsFilter_ListChanged);
測試結果是OK的!



以上希望對大家有幫助丫!


ps.搜尋到一個 BindingSource.cs 給大家參考一下。


UPDATE 2012/02/06
要怎麼樣去找到 "EVENT_POSITIONCHANGED" 呢?
看看下圖應該就可以知道了!



但是 DevExpress 好像又不是這麼一回事了!


UPDATE 2012/02/07
如果還是不通的話看一下這篇吧!
C# 如何移除未知名稱的事件
觀念是一樣的。

沒有留言:

張貼留言