Visual Studio, Forms and Inheritance
Ever have two completely unrelated problems ... only to realise they are manifestations of exactly the same issue? Sometimes it feels like a win.
I'm working on an "Analysis Wizard" in one of our client's applications, and I realised that I had to subclass the AnalysisWizard for my new CalibrationWizard. When I inherited from AnalysisWizard in CalibrationWizard, CalibrationWizard would not load in the Visual Studio Form Designer. It complained about an object reference in the base class (AnalysisWizard) constructor. But, strangely, AnalysisWizard displays fine in the Form Designer, and CalibrationWizard also shows correctly in the application.
So I put that on the back burner for a while.
Then, today, I realized that in fact, what I want is for both AnalysisWizard and CalibrationWizard to inherit from an abstract base class (say, AbstractAnalysisWizard). So I went out on Google to find if Visual Studio has some simple way to convert a concrete class into an abstract class. As you can tell, I'm not much of a VS guru yet, as will be come evident shortly.
In doing so, I saw a lot of posts along the lines of "The Visual Designer won't work if your Form extends an abstract base class." The reason for this warning: the Form Designer creates an instance of the form not by instantiating your class, but by instantiating the base class and then adding your components by parsing the InitializeComponent() method. This allows you to see a visual representation of the class even if the class you're working on doesn't yet compile, because one hopes the base class does compile and can be instantiated. It's also the reason VS inserts the boilerplate comment not to modify InitializeComponent() in the code editor, as that code not only has to compile, but also be parsed by the Form Designer. However, if the base class is abstract, it can't be instantiated and the Form Designer breaks with the error "The designer must create an instance of type 'AbstractAnalysisWizard' but it cannot because the type is declared as abstract." Funnily, you can design an abstract form class, as long as it inherits from a concrete class, for the same reason.
There are a number of workarounds available on the internet, none of which are particularly satisfying. You'd want to have the correct inheritence without muddying your code just to satisfy the Visual Designer. This technique seemed the most promising, but I couldn't get it to work correctly to allow me to attach controls from the child class to those of the parent class. Eventually, I had to use
public
#if !DEBUG
abstract
#endif
partial class AbstractAnalysisWizard : Form
{
...
and do a similar trick for the methods I want as abstract (if def them as not debug, and in the debug version, throw a NotImplemented exception). This is not an ideal situation. Hopefully putting this blog post will help someone out in the future. There was lots of talk on the various forums of how this is borked in VS 2005 and maybe it would be fixed for 'Orcas' (VS 2008), but it's still borked there, too.
However, all this work into abstract form classes points out why my original CalibrationWizard can't be displayed in the form designer, even though its parent class can. When I'm looking at the parent class (AnalysisWizard), the Form Designer is instantiating the base class (System.Windows.Form) and adding to it from its InitializeComponent(). When I try to look at the CalibrationWizard, the Form Designer tries to instantiate the parent class AnalysisWizard, and it turns out that constructor has calls to our application's data layer that aren't yet available. Hence it failure.
Weird how these two topics came together this morning.


Post new comment