I'm implementing modified version of Behavior for my Windows 8 app according to this guide. It works except one place where the Reactive framework is required:
protected override void OnAttached()
{
var evt = AssociatedObject.GetType().GetRuntimeEvent(Event);
if (evt != null)
{
Observable.FromEventPattern<RoutedEventArgs>(AssociatedObject, Event)
.Subscribe(se => FireCommand());
}
base.OnAttached();
}
The question is simple, how to achieve similar funcitonality without the Reactive frmaework? I've browsed the source of of Rx that can be obtained here, but I'ts just too complicated to me.
I've also succeeded porting to code with the only problem that it work only for fixed type of EventHandler:
protected override void OnAttached()
{
EventInfo evt = AssociatedObject.GetType().GetRuntimeEvent(Event);
if (evt != null)
{
AssignEvent<ItemClickEventHandler>(AssociatedObject, Event, FireCommand);
}
base.OnAttached();
}
protected void AssignEvent<T1>(object instance, string eventName, T1 handler)
{
EventInfo runtimeEvent = instance.GetType().GetRuntimeEvent(eventName);
Func<T1, EventRegistrationToken> add = a => (EventRegistrationToken)runtimeEvent.AddMethod.Invoke(instance, new object[] { a });
Action<EventRegistrationToken> remove = a => runtimeEvent.RemoveMethod.Invoke(runtimeEvent, new object[] { a });
WindowsRuntimeMarshal.AddEventHandler(add, remove, handler);
}
Any idea, how to make it dynamic so I don't have to use specific event handler "ItemClickEventHandler"? Note in classic .NET it' quite simple, but in WinRT I cannot use Delegate.CreateDelegate(...)
Update: Thanks to Brandon I was able to finish the method, it now looks like this:
protected override void OnAttached()
{
EventInfo evt = AssociatedObject.GetType().GetRuntimeEvent(Event);
if (evt != null)
{
MethodInfo addMethod = evt.AddMethod;
MethodInfo removeMethod = evt.RemoveMethod;
ParameterInfo[] addParameters = addMethod.GetParameters();
Type delegateType = addParameters[0].ParameterType;
Action<object, object> handler = (s, e) => FireCommand(e as RoutedEventArgs);
MethodInfo handlerInvoke = typeof(Action<object, object>).GetRuntimeMethod("Invoke", new[] { typeof(object), typeof(object) });
Delegate @delegate = handlerInvoke.CreateDelegate(delegateType, handler);
Func<object, EventRegistrationToken> add = a => (EventRegistrationToken)addMethod.Invoke(AssociatedObject, new object[] { @delegate });
Action<EventRegistrationToken> remove = t => removeMethod.Invoke(AssociatedObject, new object[] { t });
WindowsRuntimeMarshal.AddEventHandler(add, remove, handler);
}
base.OnAttached();
}
Now I can remove 800kB of Rx dlls, thanks again!