1

I am following the solution provided by Juan Carlos Diaz here

My problem is that I do not see any of the abstract class's form controls displayed in the concrete class. I am expecting them to be there so that I may use the design editor with the concrete class.

Here are the steps that I took:

  1. create a new solution
  2. create a new winforms project (.Net 4.5.2)
  3. create a Form titled AbstractBaseForm.cs, and add some hello world logic:

enter image description here

  1. add abstract keyword to AbstractBaseForm.cs; your code should look something like this:

    public abstract partial class AbstractBaseForm : Form
    {
        protected AbstractBaseForm()
        {
            InitializeComponent();
        }
    
        private void button1_Click(object sender, EventArgs e)
        {
            label1.Text = "Hello World";
        }
    }
    
  2. Add the following class to your project:

    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);
        }
    }
    
  3. Add the following attribute to AbstractBaseForm.cs:

    [TypeDescriptionProvider(typeof (AbstractControlDescriptionProvider<AbstractBaseForm, Form>))]
    public abstract partial class AbstractBaseForm : Form
    {
    
  4. Add a second Form to the project, titled ConcreteForm.cs and have it inherit from AbstractBaseForm.cs, like this:

    public partial class ConcreteForm : AbstractBaseForm
    {
        public ConcreteForm()
        {
             InitializeComponent();
        }
    }
    
  5. Change program.cs so that it loads ConcreteForm.cs like this:

    Application.Run(new ConcreteForm());
    
  6. Execute the project. You should see ConcreteForm.cs load, and clicking the button changes the label to say "Hello World".

  7. Close the application, and click on ConcreteForm.cs, bringing up its design view. You will see this:

enter image description here

Why do I not see the inherited controls from AbstractBaseForm.cs in the design view?

Community
  • 1
  • 1
sapbucket
  • 6,795
  • 15
  • 57
  • 94
  • Have you check to make sure that you are overloading the InitializeComponent() This seems to be the most likely place to start. (And that you are not using a new version generated in ConcreteForm – Lilith Daemon Jun 29 '15 at 20:59
  • @Rootix You mean override? `InitializeComponent` is a private method on the partial class generated by the IDE. It's not virtual and can not be accessed by children classes. It will get called automatically however when ever the default constructor on the child class gets invoked. – Johnathon Sullinger Jun 29 '15 at 21:23
  • 1
    Hmya, you need to stop aiming that gun at your foot and pull the trigger. The designer needs to be able to create an instance of the base class. You can fake it out by redirecting the type, but then of course that works and you'll get the behavior of the Form class. It does not have any controls. Delete the *abstract* keyword and move on with your life. – Hans Passant Jun 29 '15 at 21:47
  • @HansPassant: I think you went over my head. Let's pretend I call the following method when the button is clicked in the base class: public virtual string GetMessage() {return "Hello World";} then pretend in the child class that I do the following: public override string GetMessage() { return "Goodbye World!";} -> with your advice I would not be able to do this in fact would not be able to compile. What am I missing in your advice? – sapbucket Jun 29 '15 at 22:01
  • No. The only possible thing you could do wrong is not trying it. – Hans Passant Jun 29 '15 at 22:18

1 Answers1

2

Add a call to the base constructor

public partial class ConcreteForm : AbstractBaseForm
{
    public ConcreteForm() : base()
    {
         InitializeComponent();
    }
}

And as @hans-passant suggests, remove the abstract keyword. With the abstract keyword in place I am receiving the following error:

The designer must create an instance of type 'WindowsFormsApplication1.Form1' but it cannot because the type is declared as abstract.

benPearce
  • 37,735
  • 14
  • 62
  • 96
  • Thank you Hans and Ben. That worked perfectly AND I was still able to use virtual/override. My error was in between my ears: I thought that I was required to use an abstract class to utilize the virtual/override keywords. – sapbucket Jun 29 '15 at 22:09