문제

배경 : WPF와 C# (3.5)을 사용하고 있으며 사용자가 이미 컴파일 된 어셈블리의 일부인 양식/창/USERCONTROL을 볼 수있는 앱에서 작업 중입니다. 그들이 볼 때, 그들은 컨트롤 (버튼, 텍스트 상자, 라벨)을 클릭 할 수 있어야합니다 (작은 팝업 편집기는 컨트롤로 표시되어 툴팁, HelpId 등을 입력 할 수있는 컨트롤로 표시되어야합니다.

길고 부족 : WPF에서 기본 설계보기를 모방해야합니다. 즉, 최소한 다음을 수행해야합니다.

  • 주어진 어셈블리에서 usercontrol/창을로드하십시오 (문제 없어요)
  • Usercontrol/창을 인스턴스화하십시오 (문제 없어요)
  • 모든 컨트롤에 대해 구독 한 모든 이벤트 핸들러를 지우십시오
  • 각 컨트롤에 내 자신의 "showitorpopup"이벤트 핸들러 할당 (문제가되지 않아야합니다)

먼저, 더 쉽게 또는 더 나은 경로에 대한 제안이 있다면, 저에게 알려주십시오. (분명히 WPF에 대한 Designhost 종류의 구성 요소가 없기 때문에 (.NET 2가 읽은 것처럼) 나왔습니다.)

나는 굵은 품목에 붙어 있습니다. 가입 된 이벤트 핸들러를 지우고 있습니다. 일부 주위를 파고 반사기에 들어간 후, 나는이 멋진 위험 코드 덩어리를 생각해 냈습니다.

<Button Name="someButton" Click="someButton_Click"/>

코드는 다음과 같습니다 (원하는 경우 일부 Button_Click Eventhandler에서 실행할 수 있음).

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);
}

객체가 대상 유형과 일치하지 않습니다 (예 : 내 매개 변수 또는 대상 객체가 엉망 이됨). 나는 당신이 이것을 해결할 수 있음을 발견했습니다.

GetEventHandlers.Invoke(Activator.CreateInstance(someButton.GetType()), Params);
// Also doesn't work...

GetEventhandlers MethodInfo에서 시계를 설정하면 멋지게 보입니다. 호출을 호출 할 때 전달하는 것이 마음에 들지 않습니다.

나는 RoutedEvent 핸들러 목록을 얻는 방법의 마지막 단계에 있다고 생각합니다 (WPF RoutedEvents에서는 작동하지 않는 Good Old GetInvocationList ()와 같이). 거기에서 각 컨트롤에서 핸들러를 제거하고 이벤트가없는 양식을 갖기에 충분히 간단합니다. 그러면 내 이벤트를 추가 할 수 있습니다.

단서가 있습니까? 다시 말하지만, 전반적으로 작업을 수행하는 더 나은/쉬운 방법이 있다면 알려주세요 :)

도움이 되었습니까?

해결책

다른 접근 방식을 취하면 어떻게해야합니까? 당신은 전화 할 수 있습니다 eventManager.registerClassHandler () 모든 이벤트의 경우, 핸들러에서 (이벤트가 UI의 일부가 아닌 디자인 표면의 제어를위한 것이라고 가정) 처리 된대로 이벤트를 표시하십시오. 이는 표준 이벤트 처리기 전에 클래스 핸들러가 호출되므로 설계 표면의 컨트롤로 전달되는 것을 방지해야합니다.

컨트롤이 제공 한 이벤트 목록을 얻으려면 반사를 사용해야하지만 적어도 이런 식으로 반사를 사용하여 이벤트를 제거하지 않습니다. 또한,로드가 클래스 핸들러를 등록하는 경우 (코드가 진행되기 전에) 먼저 호출되지만, 이것이 드문 일이라고 생각합니다.

다른 팁

사용하는 경우 GetEventHandlers.Invoke(EventHandlersStore , Params) 잘 작동하고 충돌하지 않는 것 같습니다.

위의 코드를 사용하여 다음을 수행했습니다.

// Get the control's Type
Type controlViewType = ((UIElement)control).GetType();

// Dig out the undocumented (yes, I know, it's risky) EventHandlerStore
// from the control's Type
PropertyInfo EventHandlersStoreType =
controlViewType.GetProperty("EventHandlersStore",
BindingFlags.Instance | BindingFlags.NonPublic);

// Get the actual "value" of the store, not just the reflected PropertyInfo
Object EventHandlersStore = EventHandlersStoreType.GetValue(tree, null);
var miGetRoutedEventHandlers 
EventHandlersStore.GetType().GetMethod("GetRoutedEventHandlers", 
BindingFlags.Public | BindingFlags.Instance);
RoutedEventHandlerInfo[] res =   
(RoutedEventHandlerInfo[])miGetRoutedEventHandlers.Invoke(EventHandlersStore, 
new object[] { CheckedTreeViewItem.CheckedEvent });

일단 당신이 그것을 가지고 있다면, 유일한 문제는 이제 메소드 정보가 있다는 것입니다. 따라서 그 메소드를 구현하는 객체에 인스턴스를 가져와야합니다. 일반적으로 이벤트 핸들러는 창 또는 페이지 객체에 정의됩니다. var parent = VisualTreeHelper.getParent (Control); while (! (Control Is Window) &&! (Control Is Page)) {Parent = VisualTreeHelper.getParent (부모); }

그리고 그 인스턴스를 사용하면 이벤트 wtih를 호출 할 수 있습니다.

res.[0].Handler.Method.Invoke(parent, new object[] { control, new RoutedEventArgs() }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top