我想在 WinRT (Windows 8) 应用程序中使用 MVVM,我的要求之一是能够将事件与命令 ( ICommand
) 挂钩。这意味着我必须动态地将处理程序添加到 WinRT 事件。这里有一个很好的解释如何做到这一点,但我的问题是处理程序类型在编译时是未知的(即它并不总是RoutedEventHandler
像那个例子中那样)。
我开始编写该代码的通用实现,在其中使用表达式树构建委托。那部分有效。我的问题是WindowsRuntimeMarshal.AddEventHandler
动态调用失败:
var rtMarshalType = typeof (WindowsRuntimeMarshal);
var eventHandlerMethod = rtMarshalType.GetRuntimeMethods().Single(x => x.IsStatic && x.Name == "AddEventHandler");
MethodInfo closedAddMethod = eventHandlerMethod.MakeGenericMethod(handlerType);
closedAddMethod.Invoke(null, new object[] {add, remove, handler});
这在Invoke
调用中失败并引发 InvalidOperationException 并显示以下消息:
API 'System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeMarshal.AddEventHandler[ItemClickEventHandler](System.Func
2[Windows.UI.Xaml.Controls.ItemClickEventHandler,System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken], System.Action
1[System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken], Windows.UI.Xaml.Controls.ItemClickEventHandler)'当前平台。有关详细信息,请参阅http://go.microsoft.com/fwlink/?LinkId=248273 。
我知道我有正确的类型,因为当我用这个替换上面的 4 行代码时(硬编码事件处理程序类型,这不是我想要的),然后代码工作并且事件按预期附加:
WindowsRuntimeMarshal.AddEventHandler<ItemClickEventHandler>(add, remove, handler);
作为参考,三个参数定义如下(可以肯定的是,这不是我的表达式树构建代码的问题,我目前正在使用这些委托的显式定义,即使尝试动态调用AddEventHandler
,仍然失败):
Func<ItemClickEventHandler, EventRegistrationToken> add =
a => (EventRegistrationToken) eventInfo.AddMethod.Invoke(instance, new object[] {a});
Action<EventRegistrationToken> remove = a => eventInfo.RemoveMethod.Invoke(instance, new object[] {a});
ItemClickEventHandler handler = (s, args) => command.Execute(args);
为什么通过反射调用而不是直接调用时调用失败?
当编译时事件处理程序的类型未知时,是否有用于动态附加 WinRT 事件的替代解决方案?