Maybe you have just spotted the following problem with Visual Studio 2005 : you can create an abstract form, which inherits System.Windows.Forms.Form, and modify it in the visual designer. But if you inherit it, you cannot modify it in the visual designer. You think it is kind of strange, but the explanation is pretty clear. And so is the workaround. You are now armed to modify visual control, even if they inherit from an abstract control.

But the things are slightly different when dealing with generics : you can create a generic form and modify it in the visual designer. But if you create a specialized child of this form, the visual designer refuses to open it. Even with the previous trick, there is nothing to do. After some search and some experiment, I came to the conclusion that the behaviour of the CodeDomDesignerLoader is far away from my understanding. So, are we lost in space when dealing with generic controls ?

No. The workaround to this behaviour is pretty ugly, but it has one huge advantage : it works. So here is an example.

  1. Define your generic form, like any other generic class :

        1 using System.Windows.Forms;

        2 

        3 namespace AbstractAndGeneric

        4 {

        5     public partial class GenericForm<T> : Form

        6     {

        7         public GenericForm()

        8         {

        9             InitializeComponent();

       10         }

       11     }

       12 }

  2. Define your specific form, by inheriting the generic form and specialize it with a type :

        1 using System;

        2 

        3 namespace AbstractAndGeneric

        4 {

        5     public partial class SpecificForm : GenericForm<String>

        6     {

        7         public SpecificForm()

        8         {

        9             InitializeComponent();

       10         }

       11     }

       12 }

  3. At this point, if you try to open SpecificForm in the designer, you will get a nice error message.
  4. Add the following code to the SpecificForm :

        1 using System;

        2 

        3 namespace AbstractAndGeneric

        4 {

        5 #if DEBUG

        6     public partial class SpecificForm : __SpecificForm

        7 #else

        8     public partial class SpecificForm : GenericForm<String>

        9 #endif

       10     {

       11         public SpecificForm()

       12         {

       13             InitializeComponent();

       14         }

       15     }

       16 

       17 #if DEBUG

       18     public partial class __SpecificForm : GenericForm<String>

       19     {

       20     }

       21 #endif

       22 }

The explanation is straighforward :

  • Considering the behaviour of the designer, if the base class of the control you want to design is not designable, you got an error. That is why, an intermediate class is inserted. Its sole purpose is to provide a designable class for the visual designer.
  • The use of compilation directives allows to use the trick in the Debug configuration and to have a direct inheritance in the Release configuration.
  • And I repeat, this trick only works if you design in Debug mode. Otherwise, you will get the usual error.

This is the solution I found, but I am looking forward to see an alternative solution, simpler and more elegant.