-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Private EventHandlers throw an exception on XAML-defined custom control, inherited by other control #11467
Comments
We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process. |
cc @mattleibow |
This seems interesting @StephaneDelcroix... It appears the derived type is looking to attach the event from the derived type to the base, but the event handler is in the base... Not sure if that makes sense, but the repro shows an exception for me in the latest net7.0 code too. |
If I understand this correctly, you would get the same result from c#. if you want to access methods from derived types, |
Fixes: dotnet#11467 Context: https://github.com/maiia-kuzmishyna/MAUI-ProtectedEventHandlers Reviewing the customer sample, it appears to be a valid case. Consider a `ChildButton` defined in XAML: <local:ParentButton xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:foo" x:Class="foo.ChildButton"> </local:ParentButton> Where `ParentButton` is also defined in XAML: <Button xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="foo.ParentButton" Clicked="ParentButton_OnClicked"> </Button> Where `ParentButton_OnClicked` is of course private: private void ParentButton_OnClicked(object sender, EventArgs e) { } Throws an exception at runtime with: No method ParentButton_OnClicked with correct signature found on type foo.ChildButton What was also odd, it appears the problem just "goes away" in Release mode, meaning it works under XamlC. This kind of points to a bug with non-compiled XAML. It appears the problem was the code: foreach (var mi in rootElement.GetType().GetRuntimeMethods()) { //... if (mi.Name == (string)value) { addMethod.Invoke(element, new[] { mi.CreateDelegate(eventInfo.EventHandlerType, mi.IsStatic ? null : rootElement) }); return true; } //... } In this example, `rootElement` is of type `ChildButton` while the method is on type `ParentButton`. As mentioned on: https://stackoverflow.com/a/2267299 You need to access `Type.BaseType` to find private methods on base types. I changed this to instead: * Iterate over `rootElement.GetType()` and its base types. * Call `Type.GetMethod()` using the method name, passing the appropriate `BindingFlags`. This appears to make the new test pass, solving the issue.
Fixes #11467 Context: https://github.com/maiia-kuzmishyna/MAUI-ProtectedEventHandlers Reviewing the customer sample, it appears to be a valid case. Consider a `ChildButton` defined in XAML: <local:ParentButton xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:foo" x:Class="foo.ChildButton"> </local:ParentButton> Where `ParentButton` is also defined in XAML: <Button xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="foo.ParentButton" Clicked="ParentButton_OnClicked"> </Button> Where `ParentButton_OnClicked` is of course private: private void ParentButton_OnClicked(object sender, EventArgs e) { } Throws an exception at runtime with: No method ParentButton_OnClicked with correct signature found on type foo.ChildButton What was also odd, it appears the problem just "goes away" in Release mode, meaning it works under XamlC. This kind of points to a bug with non-compiled XAML. It appears the problem was the code: foreach (var mi in rootElement.GetType().GetRuntimeMethods()) { //... if (mi.Name == (string)value) { addMethod.Invoke(element, new[] { mi.CreateDelegate(eventInfo.EventHandlerType, mi.IsStatic ? null : rootElement) }); return true; } //... } In this example, `rootElement` is of type `ChildButton` while the method is on type `ParentButton`. As mentioned on: https://stackoverflow.com/a/2267299 You need to access `Type.BaseType` to find private methods on base types. I changed this to instead: * Iterate over `rootElement.GetType()` and its base types. * Call `Type.GetMethod()` using the method name, passing the appropriate `BindingFlags`. This appears to make the new test pass, solving the issue.
Fixes: dotnet#11467 Context: https://github.com/maiia-kuzmishyna/MAUI-ProtectedEventHandlers Reviewing the customer sample, it appears to be a valid case. Consider a `ChildButton` defined in XAML: <local:ParentButton xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:foo" x:Class="foo.ChildButton"> </local:ParentButton> Where `ParentButton` is also defined in XAML: <Button xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="foo.ParentButton" Clicked="ParentButton_OnClicked"> </Button> Where `ParentButton_OnClicked` is of course private: private void ParentButton_OnClicked(object sender, EventArgs e) { } Throws an exception at runtime with: No method ParentButton_OnClicked with correct signature found on type foo.ChildButton What was also odd, it appears the problem just "goes away" in Release mode, meaning it works under XamlC. This kind of points to a bug with non-compiled XAML. It appears the problem was the code: foreach (var mi in rootElement.GetType().GetRuntimeMethods()) { //... if (mi.Name == (string)value) { addMethod.Invoke(element, new[] { mi.CreateDelegate(eventInfo.EventHandlerType, mi.IsStatic ? null : rootElement) }); return true; } //... } In this example, `rootElement` is of type `ChildButton` while the method is on type `ParentButton`. As mentioned on: https://stackoverflow.com/a/2267299 You need to access `Type.BaseType` to find private methods on base types. I changed this to instead: * Iterate over `rootElement.GetType()` and its base types. * Call `Type.GetMethod()` using the method name, passing the appropriate `BindingFlags`. This appears to make the new test pass, solving the issue.
Description
When I define a custom control in XAML that subscribes to some event handlers and those event handlers are private (ParentControl), and then I have a different control inheriting ParentControl (ChildControl) -
Application crashes with exception:
"No method ParentButton_OnClicked with correct signature found on type ProtectedEventHandlers.ChildButton".
If I just use ParentButton instead of ChildButton, or make event handler protected - works without errors.
Steps to Reproduce
Link to public reproduction project repository
https://github.com/maiia-kuzmishyna/MAUI-ProtectedEventHandlers
Version with bug
6.0.400
Last version that worked well
Unknown/Other
Affected platforms
iOS, Android, Windows
Affected platform versions
iOS 15,16; Windows 11; Android 31
Did you find any workaround?
Make Event Handler protected instead of private.
Relevant log output
No response
The text was updated successfully, but these errors were encountered: