Справочная информация: я использую WPF и C # (3.5) и работаю над приложением, которое позволяет пользователю просматривать форму / window / usercontrol, которая уже является частью скомпилированной сборки. Когда они просматривают его, они должны иметь возможность щелкать по любому элементу управления (кнопкам, текстовым полям, даже надписям), рядом с элементом управления должен появиться небольшой всплывающий редактор, где они могут затем ввести подсказку, helpID и т. Д. Для этого элемента управления.
Короче говоря: мне нужно имитировать базовый дизайн в WPF. Что означает, что мне нужно сделать по крайней мере следующее:
- Загрузка пользовательского элемента управления / окна из данной сборки (без проблем)
- Создайте его в пользовательском контроле / окне (без проблем)
- Очистить все подписанные EventHandlers для всех его элементов управления
- Назначьте свой собственный EventHandler «ShowEditorPopup» для каждого элемента управления (не должно быть проблемой)
Прежде всего, если у кого-то есть предложения по более легкому или лучшему маршруту, пожалуйста, дайте мне знать. (Очевидно, что нет никакого компонента DesignHost для WPF (как я читал .NET 2), так что это не так.)
Я застрял на выделенном элементе - очищаю все подписанные EventHandlers. После того, как я покопался в некоторых и попал в Reflector, я нашел этот классный кусок опасного кода (здесь я просто пытаюсь получить все EventHandlers для одной кнопки с именем someButton, определенной в XAML):
<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);
}
Работает до Invoke, который возвращает: Объект не соответствует типу цели (т. Е. Мои параметры или целевой объект перепутаны). Я обнаружил, что вы можете решить эту проблему с помощью:
GetEventHandlers.Invoke(Activator.CreateInstance(someButton.GetType()), Params);
// Also doesn't work...
Когда я устанавливаю часы в методе GetEventHandlers, он выглядит великолепно, ему просто не нравится то, что я передаю, когда я вызываю Invoke.
Мне кажется, что я на самом последнем этапе получения списка обработчиков RoutedEvent (например, старого доброго GetInvocationList (), который, очевидно, не работает для WPF RoutedEvents). Оттуда будет достаточно просто удалить эти обработчики из каждого элемента управления и получить форму без событий, к которой я затем смогу добавить свои собственные события.
Есть какие-нибудь подсказки? Опять же, если есть лучший / более простой способ выполнить задачу в целом, дайте мне знать:)