ckfinite
Topic Author
Posts: 2
Joined: 27 Feb 2022, 19:23

Custom RoutedEventArgs in the managed API

05 Apr 2022, 06:31

I'm trying to create a new custom routedevent with my own RoutedEventArgs. Following the WPF idiom, I create a subclass of RoutedEventArgs such as (with application specific fields removed):
  class ResizeEventArgs : RoutedEventArgs
  {
    public ResizeEventArgs(RoutedEvent @event, object sender) : 
      base(@event, sender)
      { }
  }
    
When I attempt to use this in a custom RoutedEvent, Noesis complains that:
InvalidOperationException: Event args for ResizeEventHandler have to define the method 'static void InvokeHandler(Delegate handler, IntPtr sender, IntPtr args)'
Implementing InvokeHandler is a challenge; looking at the provided implementations of RoutedEventArgs, the interface assumes that they are P/Invoke wrappers and pass them a IntPtr of the internal native EventArgs. For example,
  internal static new void InvokeHandler(Delegate handler, IntPtr sender, IntPtr args) {
    ScrollChangedEventHandler handler_ = (ScrollChangedEventHandler)handler;
    if (handler_ != null) {
      handler_(Extend.GetProxy(sender, false), new ScrollChangedEventArgs(args, false));
    }
  }
Is there a way to use Marshal or unsafe, for example, to recover the managed object from the native pointer passed to InvokeHandler? I'm not particularly good at debugging across the managed/native boundary, so am having a bit of a hard time introspecting on the memory at the args pointer to figure out if I can do this myself.
 
User avatar
sfernandez
Site Admin
Posts: 2983
Joined: 22 Dec 2011, 19:20

Re: Custom RoutedEventArgs in the managed API

05 Apr 2022, 10:32

I guess your custom args class defines some property/field members and that is why you want to recover the original managed object, right?
We should provide the same API as WPF to implement a custom routed event without requiring anything else, could you please report it in our bugtracker?

In the meantime, if your args class doesn't have any members then you can define it like this:
public class ResizeEventArgs : RoutedEventArgs
{
    public ResizeEventArgs(RoutedEvent @event, object sender) : base(@event, sender) { }
    private ResizeEventArgs(IntPtr ptr, bool ownMemory): base(ptr, ownMemory) { }
    private static void InvokeHandler(Delegate handler, IntPtr sender, IntPtr args)
    {
        ((ResizeEventHandler)handler)?.Invoke(BaseComponent.GetProxy(sender), new ResizeEventArgs(args, false));
    }
}
 
ckfinite
Topic Author
Posts: 2
Joined: 27 Feb 2022, 19:23

Re: Custom RoutedEventArgs in the managed API

05 Apr 2022, 21:17

I guess your custom args class defines some property/field members and that is why you want to recover the original managed object, right?
Yes, that's right - thank you for the help. The feature request is here.
In the meantime, if your args class doesn't have any members then you can define it like this:
It doesn't seem like BaseComponent has a method GetProxy on it?
 
User avatar
sfernandez
Site Admin
Posts: 2983
Joined: 22 Dec 2011, 19:20

Re: Custom RoutedEventArgs in the managed API

11 Apr 2022, 11:36

Thanks for the report, we will fix it as soon as possible.

Regarding GetProxy(), it is defined in BaseComponentExtend.cs file, don't you have that? Which version of Noesis are you using?
Anyway, if you cannot get the members of your custom args until we solve it, is probably better to use simple RoutedEventArgs in your event for the time being.

Who is online

Users browsing this forum: Bing [Bot] and 40 guests