Bug 2927 - Xaml throws exception when binding events
Summary: Xaml throws exception when binding events
Status: RESOLVED FIXED
Alias: None
Product: Class Libraries
Classification: Mono
Component: System.XML ()
Version: 2.10.x
Hardware: PC Mac OS
: Low normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2012-01-17 01:04 UTC by Curtis Wensley
Modified: 2012-01-19 04:34 UTC (History)
4 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Test to ensure events are hooked up correctly from xaml (16.64 KB, application/zip)
2012-01-17 01:04 UTC, Curtis Wensley
Details
test case mentioned earlier. (1.93 KB, text/plain)
2012-01-19 04:05 UTC, Atsushi Eno
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Curtis Wensley 2012-01-17 01:04:57 UTC
Created attachment 1211 [details]
Test to ensure events are hooked up correctly from xaml

Using System.Xaml to bind events does not work and throws an exception.

A sample app is provided to repro the issue.

Expected results:

Event was hooked up correctly
Object loaded: TestXaml.Items.MyParent

Actual results:

Unhandled Exception: System.Xaml.XamlObjectWriterException: Value 'HandleMyEvent' (of type System.String) is not of or convertible to type {clr-namespace:System;assembly=mscorlib}EventHandler({clr-namespace:System;assembly=mscorlib}EventArgs)
  at System.Xaml.XamlObjectWriterInternal.DoGetCorrectlyTypedValue (System.Xaml.XamlType xt, System.Object value) [0x00160] in /private/tmp/monobuild/build/BUILD/mono-2.10.8.1/mcs/class/System.Xaml/System.Xaml/XamlObjectWriter.cs:472 
  at System.Xaml.XamlObjectWriterInternal.GetCorrectlyTypedValue (System.Xaml.XamlType xt, System.Object value) [0x00000] in /private/tmp/monobuild/build/BUILD/mono-2.10.8.1/mcs/class/System.Xaml/System.Xaml/XamlObjectWriter.cs:421 
[ERROR] FATAL UNHANDLED EXCEPTION: System.Xaml.XamlObjectWriterException: Value 'HandleMyEvent' (of type System.String) is not of or convertible to type {clr-namespace:System;assembly=mscorlib}EventHandler({clr-namespace:System;assembly=mscorlib}EventArgs)
  at System.Xaml.XamlObjectWriterInternal.DoGetCorrectlyTypedValue (System.Xaml.XamlType xt, System.Object value) [0x00160] in /private/tmp/monobuild/build/BUILD/mono-2.10.8.1/mcs/class/System.Xaml/System.Xaml/XamlObjectWriter.cs:472 
  at System.Xaml.XamlObjectWriterInternal.GetCorrectlyTypedValue (System.Xaml.XamlType xt, System.Object value) [0x00000] in /private/tmp/monobuild/build/BUILD/mono-2.10.8.1/mcs/class/System.Xaml/System.Xaml/XamlObjectWriter.cs:421
Comment 1 Miguel de Icaza [MSFT] 2012-01-18 10:39:40 UTC
Hooking up events does not seem to be supported in our System.Xaml implementation.

Not sure when we are going to get around adding support for that, but I CCed those that might know more.
Comment 2 Atsushi Eno 2012-01-18 21:29:27 UTC
We do support events in git master version of System.Xaml (unlike 2.10). It goes somewhat further.

$ mono --debug bin/Debug/TestXaml.exe

Unhandled Exception: System.Xaml.XamlObjectWriterException: Referenced value met
hod HandleMyEvent in type HandleMyEvent indicated by event {http://schemas.examp
le.com/test}Child.MyEvent was not found
  at System.Xaml.XamlObjectWriterInternal.SetEvent (System.Xaml.XamlMember membe
r, System.String value) [0x00147] in C:\cygwin\home\atsushi\svn\mono\mcs\class\S
ystem.Xaml\System.Xaml\XamlObjectWriter.cs:377
  at System.Xaml.XamlObjectWriterInternal.OnWriteEndMember () [0x001e3] in C:\cy
gwin\home\atsushi\svn\mono\mcs\class\System.Xaml\System.Xaml\XamlObjectWriter.cs
:350
  at System.Xaml.XamlWriterInternalBase.WriteEndMember () [0x0000b] in C:\cygwin
\home\atsushi\svn\mono\mcs\class\System.Xaml\System.Xaml\XamlWriterInternalBase.
cs:213
  at System.Xaml.XamlObjectWriter.WriteEndMember () [0x00000] in C:\cygwin\home\
atsushi\svn\mono\mcs\class\System.Xaml\System.Xaml\XamlObjectWriter.cs:199
  at System.Xaml.XamlWriter.WriteNode (System.Xaml.XamlReader reader) [0x00079]
in C:\cygwin\home\atsushi\svn\mono\mcs\class\System.Xaml\System.Xaml\XamlWriter.
cs:75
  at System.Xaml.XamlServices.Transform (System.Xaml.XamlReader xamlReader, Syst
em.Xaml.XamlWriter xamlWriter, Boolean closeWriter) [0x00039] in C:\cygwin\home\
atsushi\svn\mono\mcs\class\System.Xaml\System.Xaml\XamlServices.cs:123
  at System.Xaml.XamlServices.Transform (System.Xaml.XamlReader xamlReader, Syst
em.Xaml.XamlWriter xamlWriter) [0x00000] in C:\cygwin\home\atsushi\svn\mono\mcs\
class\System.Xaml\System.Xaml\XamlServices.cs:109
  at TestXaml.MainClass.Main (System.String[] args) [0x0004b] in C:\Users\atsush
i\Desktop\TestXamlEvents\TestXaml\TestXaml\Main.cs:23
[ERROR] FATAL UNHANDLED EXCEPTION: System.Xaml.XamlObjectWriterException: Refere
nced value method HandleMyEvent in type HandleMyEvent indicated by event {http:/
/schemas.example.com/test}Child.MyEvent was not found
  at System.Xaml.XamlObjectWriterInternal.SetEvent (System.Xaml.XamlMember membe
r, System.String value) [0x00147] in C:\cygwin\home\atsushi\svn\mono\mcs\class\S
ystem.Xaml\System.Xaml\XamlObjectWriter.cs:377
  at System.Xaml.XamlObjectWriterInternal.OnWriteEndMember () [0x001e3] in C:\cy
gwin\home\atsushi\svn\mono\mcs\class\System.Xaml\System.Xaml\XamlObjectWriter.cs
:350
  at System.Xaml.XamlWriterInternalBase.WriteEndMember () [0x0000b] in C:\cygwin
\home\atsushi\svn\mono\mcs\class\System.Xaml\System.Xaml\XamlWriterInternalBase.
cs:213
  at System.Xaml.XamlObjectWriter.WriteEndMember () [0x00000] in C:\cygwin\home\
atsushi\svn\mono\mcs\class\System.Xaml\System.Xaml\XamlObjectWriter.cs:199
  at System.Xaml.XamlWriter.WriteNode (System.Xaml.XamlReader reader) [0x00079]
in C:\cygwin\home\atsushi\svn\mono\mcs\class\System.Xaml\System.Xaml\XamlWriter.
cs:75
  at System.Xaml.XamlServices.Transform (System.Xaml.XamlReader xamlReader, Syst
em.Xaml.XamlWriter xamlWriter, Boolean closeWriter) [0x00039] in C:\cygwin\home\
atsushi\svn\mono\mcs\class\System.Xaml\System.Xaml\XamlServices.cs:123
  at System.Xaml.XamlServices.Transform (System.Xaml.XamlReader xamlReader, Syst
em.Xaml.XamlWriter xamlWriter) [0x00000] in C:\cygwin\home\atsushi\svn\mono\mcs\
class\System.Xaml\System.Xaml\XamlServices.cs:109
  at TestXaml.MainClass.Main (System.String[] args) [0x0004b] in C:\Users\atsush
i\Desktop\TestXamlEvents\TestXaml\TestXaml\Main.cs:23

The reason why it fails is that it refers to "HandleMyEvent" which is in *parent* instance (MyParent) and to my understanding it is not authorized (documented) way to reference a method as an event value, hence I never supported such lookup.

To fix this issue, I need information on *what* can be specified for an event value in xaml.
Comment 3 Curtis Wensley 2012-01-18 21:40:44 UTC
Hm, I believe it may not be working because it is not using the XamlObjectWriterSettings.RootObjectInstance passed in to the writer as the root instance, but instead creates a new instance regardless.  

I forgot to add the x:Class attribute into the sample xaml file, which would make it properly specify to use  the MyParent class instead of the Parent class, though in MS.NET it works without:

<Parent xmlns="http://schemas.example.com/test" 
		xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"		
		x:Class="TextXaml.Items.MyParent">
	...
</Parent>

I'm in the process of building git master as I noticed a lot of changes in System.Xaml compared to 2.10.8, and will submit bugs based on master.
Comment 4 Curtis Wensley 2012-01-18 23:17:00 UTC
Ok, looks like the git master code DOES use MyParent correctly when properly defined.

Found some info about how this should work: http://msdn.microsoft.com/en-us/library/ms752059.aspx#events_and_xaml_codebehind
Comment 5 Atsushi Eno 2012-01-19 00:32:16 UTC
This MSDN page linked from your URL says:

"These methods must be defined by the partial class within the CLR namespace identified by x:Class."

http://msdn.microsoft.com/en-us/library/aa970568.aspx#Code_behind__Event_Handler__and_Partial_Class

So if it works without any x:Class attribute, it is pretty much unexpected undocumented behavior (bug in .NET).

Unless there is information on the actual behavior, we cannot do anything closer and I'll close the bug as FEATURE.
Comment 6 Curtis Wensley 2012-01-19 00:44:15 UTC
Right.  I'm not asking for it to work without the x:Class attribute.  I'm asking that it does work as documented.

Right now, it looks as if it is looking for the event handler in the current node's object, as opposed to the root object's partial class, even when defining the x:Class attribute.

For the msdn example I linked, it would be looking for Button.Button_Click, instead of ExamplePage.Button_Click..

In XamlObjectWriter.SetEvent, it does the following:

var mi = xt.UnderlyingType.GetMethod (mn, (from pi in eventMethodParams select pi.ParameterType).ToArray ());

From what I can gather, xt.UnderlyingType is the event's declaring type (e.g. in the test app, Child, or in the case on msdn, Button), but this should always be looking at the root object since binding an event to a method on the same object doesn't make any sense (to me, at least), and would make binding events, well, unusable methinks..
Comment 7 Curtis Wensley 2012-01-19 01:52:50 UTC
ok, did some quick hacking on mono to get this to work similarly to the msdn example:

https://github.com/cwensley/mono/commit/e53153e95ce3e49a391762171da0daa764fd8669

Probably not implemented in the most exquisite fashion, but you get the idea
Comment 8 Atsushi Eno 2012-01-19 04:04:19 UTC
Curtis, thanks for the inspection, I'm going to apply your change with one fix.

For the rerocrd, what scared me of that change (I actually thought of about that) was that it is not very obvious that XamlObjectWriter looks only for the root instance; there might be some objects of classes between the target object and the root instance that may also have corresponding methods. I'm going to attach a repro that all Root/Child/Descendant classes have HandleMyEvent() function - on .NET this actually binds to Root.HandleMyEvent(), so your assumption on the behavior is right without problem.

One tiny fix I made to your change was that XamlObjectWriter does not only look for the declared method. So, I removed BindingFlags.DeclaredOnly. (You can verify the behavior by modifying my repro code to move HandleMyEvent() method from MyRootClass to RootClass and see results for "xml2".
Comment 9 Atsushi Eno 2012-01-19 04:05:29 UTC
Created attachment 1230 [details]
test case mentioned earlier.

compile this as events.cs to get correct XAML element right.
Comment 10 Atsushi Eno 2012-01-19 04:34:40 UTC
Applied the fix and added corresponding tests in git master 62537fd. Thanks!