Alex Rivera | Logout

Why "Setting event handlers inside a Setter.Value structure" gives compilation error?

Asked 2011-04-12T10:49:13.110
9

I faced the problem exactly as described in Setting event handlers inside a Setter.Value structure. But I want to understand why the solution provided by the question's author doesn't work. It looks like I missed some concept.

Edit
Report

1 Answer

20

This appears to be a bug in the generation of the XAML code-behind. In addition to the user code-behind for XAML files, there is a "compiler" generated version that defines InitializeComponent and class fields for named elements (i.e. x:Name).

Given a simple example:

<Window.Resources>
    <Style TargetType="Button">
        <Setter Property="ContextMenu">
            <Setter.Value>
                <ContextMenu>
                    <MenuItem Header="Header" Click="MenuItem_Click"/>
                </ContextMenu>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

<Button />

If you run this, you will get the following exception:

System.Windows.Markup.XamlParseException occurred
  Message='Set connectionId threw an exception.' Line number '13' and line position '8'.
  Source=PresentationFramework
  LineNumber=13
  LinePosition=8
  StackTrace:
       at System.Windows.Markup.XamlReader.RewrapException(Exception e, IXamlLineInfo lineInfo, Uri baseUri)
  InnerException: System.InvalidCastException
       Message=Unable to cast object of type 'System.Windows.Controls.MenuItem' to type 'System.Windows.Controls.Button'.
       Source=Windows7Theme
       StackTrace:
            at Windows7Theme.MainWindow.System.Windows.Markup.IComponentConnector.Connect(Int32 connectionId, Object target) in c:\Users\TJoe\Documents\Visual Studio 10\Projects\Windows7Theme\Windows7Theme\MainWindow.xaml:line 13
            at MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetConnectionId(Object root, Int32 connectionId, Object instance)
       InnerException: 

The generated code-behind files can be found in the obj folder, so if we examine that we can see the following code:

void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
    switch (connectionId)
    {
answered 2011-04-12T23:43:42.083

Your Answer