背景:我正在使用WPF和C#(3.5),並且正在開發一個應用程序,該應用程序允許用戶查看已經是編譯程序集的一部分的窗體/窗口/用戶控件。當他們查看它時,他們應該能夠點擊任何控件(按鈕,文本框,甚至標籤),控件上應該出現一個小小的彈出窗口編輯器,然後可以在該控件中輸入工具提示,helpID等。通過反射去除路由事件處理程序?
它的長短:我需要模仿WPF中的基本設計視圖。這意味着我至少需要做到以下幾點:
- 負載從一個給定的裝配(沒問題)的用戶控件/窗口
- 中實例化用戶控件/窗口(沒問題)
- 清除其所有控制
- 指定我自己的「ShowEditorPopup」事件處理程序,以每個控制所有訂閱的事件處理器(不應該是一個問題)
首先,如果有人對更簡單或更好的路線有任何建議,請讓我知道。 (顯然,WPF沒有DesignHost類型的組件(就像我已經讀過.NET 2一樣),所以這是不可能的。)
我被困在粗體項目 - 清除任何訂閱的EventHandlers。在挖掘了一些並進入Reflector之後,我想出了這個很酷的危險代碼塊(在這裏,我只是想讓所有的EventHandlers在XAML中定義一個叫someButton的Button):
<Button Name="someButton" Click="someButton_Click"/>
下面的代碼(你可以,如果你想從someButton_Click事件處理程序運行它):
public void SomeFunction()
{
// Get the control's Type
Type someButtonType = ((UIElement)someButton).GetType();
// Dig out the undocumented (yes, I know, it's risky) EventHandlerStore
// from the control's Type
PropertyInfo EventHandlersStoreType =
someButtonType.GetProperty("EventHandlersStore",
BindingFlags.Instance | BindingFlags.NonPublic);
// Get the actual "value" of the store, not just the reflected PropertyInfo
Object EventHandlersStore = EventHandlersStoreType.GetValue(someButton, null);
// Get the store's type ...
Type storeType = EventHandlersStore.GetType();
// ... so we can pull out the store's public method GetRoutedEventHandlers
MethodInfo GetEventHandlers =
storeType.GetMethod("GetRoutedEventHandlers",
BindingFlags.Instance | BindingFlags.Public);
// Reflector shows us that the method's sig is this:
// public RoutedEventHandlerInfo[] GetRoutedEventHandlers(RoutedEvent routedEvent);
// So set up the RoutedEvent param
object[] Params = new object[] { ButtonBase.ClickEvent as RoutedEvent };
// I've also seen this for the param, but doesn't seem to make a difference:
// object[] Params = new object[] { someButton.ClickEvent };
// And invoke it ... and watch it crash!
GetEventHandlers.Invoke(someButton, Params);
}
它的工作原理到調用,它返回:對象不匹配目標類型(即我params中,目標對象被弄亂)。我發現你可以解決此問題:
GetEventHandlers.Invoke(Activator.CreateInstance(someButton.GetType()), Params);
// Also doesn't work...
當我設置監視那個GetEventHandlers的MethodInfo,它看起來很棒,它只是不喜歡什麼,我路過它時,我所說的調用。
我覺得我在最後一步如何獲得RoutedEvent處理程序的列表(如舊的GetInvocationList(),顯然不適用於WPF RoutedEvents)。從那裏,它將會非常簡單,從每個控件中移除這些處理程序,並擁有一個無事件形式,然後我可以添加自己的事件。
任何線索?再次,如果有更好/更簡單的方法來完成整個任務,請讓我知道:)
哇,你是一個偉大的工作,我只是想這樣做。你只是給了我需要的出發點。 – orellabac 2013-04-06 17:44:32