0

I got a weird warning that I don't understand.

I have two UserControls. The first one BaseControl inherits from Button and the second SecondControl inherits from BaseControl. I didn't change anything so both UserControls are like VS2012 creates them (default constructor etc.) I only removed the sealed keyword of BaseControl in order to inherit it.

Now if I build the project the following warning is put out:

'MyProject.Controls.SecondControl.Connect(int, object)' hides inherited member
'MyProject.Controls.BaseControl.Connect(int, object).' Use the new keyword if hiding was intended.

When I click on this warning, VS2012 opens a file named 'SecondControl.g.cs' and shows this:

partial class SecondControl: global::MyProject.Controls.BaseControl, global::Windows.UI.Xaml.Markup.IComponentConnector
{
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Windows.UI.Xaml.Build.Tasks"," 4.0.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]

    public void Connect(int connectionId, object target)
    {
        this._contentLoaded = true;
    }
}

What does this mean? I don't have any method called Connect() except for this in SecondControl.g.cs but that is none of my methods. Any hint how to fix this? Even it is only a warning and my application works fine, I don't like to have any warnings/errors in the output window :)

I found some articles about this error on SO but none of these helped me :(

Edit: Adding the whole classes mentioned above.

BaseControl:

namespace MyProject.Controls
{
    public partial class BaseControl : Button
    {
        public BaseControl()
        {
            this.InitializeComponent();
        }
    }
}

SecondControl:

namespace MyProject.Controls
{
    public sealed partial class SecondControl: BaseControl
    {
        public SecondControl()
        {
            this.InitializeComponent();
        }
    }
}

I checked the whole inheritance chain of Windows.UI.Xaml.Controls.Button and there is no Connect(int, object) or any other Connect(). I didn't add any Connect()-method too.

TorbenJ
  • 4,462
  • 11
  • 47
  • 84

1 Answers1

3

You can't create a control from a UserControl and have it be a Button AND have derived controls. The BaseControl needs to be a sealed UserControl. You could make the UserControl act like a button and/or contain a button.

The docs for IComponentContainer are partially the clue as to why things are going wrong.

It's trying to wire up the UI using the Connect method that is added to the generated class for UserControls. But, by having multiple classes defined for the same XAML (or different XAML), it's generating the Connect method for each class (BaseControl and SecondControl in your example). That's why it was sealed to begin with: to prevent this from happening. You can't reliably have a UI in XAML used by one class and then create a derived class easily. As you can see, the build and VS gets messed up (it's had this problem for many years with WinForms, WPF, ASP.NET WebForms, and Silverlight).

What you likely want to do instead is to create a Templated Control. This gives you the ability to define a UI still in XAML (and modify it in subclasses potentially). That's how the button was originally created in the WinRT (and its ancestors Silverlight and WPF).

You'll end up creating a Style in a ResourceDictionary:

<Style TargetType="local:CustomControl1">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:CustomControl1">
                <Border
                    Background="{TemplateBinding Background}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}">
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

And a class that uses that Style:

public sealed class CustomControl1 : Control
{
    public CustomControl1()
    {
        this.DefaultStyleKey = typeof(CustomControl1);
    }
}
WiredPrairie
  • 58,954
  • 17
  • 116
  • 143