Abstract UserControl inheritance in Visual Studio designer

Even though this question is years old, I'd like to add what I've found.

If you don't want to touch your abstract base class, you can do this hack:

abstract class CustomControl : UserControl 
{
    protected abstract int DoStuff();
}

class BaseDetailControl : CustomControl
{
    protected override int DoStuff()
    {
        throw new InvalidOperationException("This method must be overriden.");
    }
}

class DetailControl : BaseDetailControl
{
    protected override int DoStuff()
    { 
        // do stuff
        return result;
    }
}

This way, your form inherits from a non-abstract base form and it's displayed in the designer! And you keep your abstract form, but only one more level up in the inheritance. Strange, isn't it?


Another way to solve this is using pre-processing directives.

#if DEBUG
  public class UserControlAdmonEntidad : UserControl, IAdmonEntidad
#else
  public abstract class UserControlAdmonEntidad : UserControl, IAdmonEntidad
#endif
  {
    ...
    #if DEBUG
    public virtual object DoSomething()
    {
        throw new NotImplementedException("This method must be implemented!!!");
    }
    #else
    public abstract object DoSomething();
    #endif

    ...
  }

See this link for more information regarding this topic: Inheriting a Form from an Abstract Class (and Making it Work in the Designer)

The same solution was also mentioned in this MSDN forum thread, in a briefer way: UserControl, Inherited Control, Abstract class, (C#)

Maybe is not the cleaner solution, but it's still the shortest I have found.


You can use a TypeDescriptionProviderAttribute to provide a concrete design-time implementation for your abstract base class. See http://wonkitect.wordpress.com/2008/06/20/using-visual-studio-whidbey-to-design-abstract-forms/ for details.


What we want

First, let's define the final class and the base abstract class.

public class MyControl : AbstractControl
...
public abstract class AbstractControl : UserControl // Also works for Form
...

Now all we need is a Description provider.

public class AbstractControlDescriptionProvider<TAbstract, TBase> : TypeDescriptionProvider
{
    public AbstractControlDescriptionProvider()
        : base(TypeDescriptor.GetProvider(typeof(TAbstract)))
    {
    }

    public override Type GetReflectionType(Type objectType, object instance)
    {
        if (objectType == typeof(TAbstract))
            return typeof(TBase);

        return base.GetReflectionType(objectType, instance);
    }

    public override object CreateInstance(IServiceProvider provider, Type objectType, Type[] argTypes, object[] args)
    {
        if (objectType == typeof(TAbstract))
            objectType = typeof(TBase);

        return base.CreateInstance(provider, objectType, argTypes, args);
    }
}

Finally we just apply a TypeDescriptionProvider attribute to the Abstract control.

[TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider<AbstractControl, UserControl>))]
public abstract class AbstractControl : UserControl
...

And that's it. No middle control required.

And the provider class can be applied to as many Abstract bases as we want in the same solution.