The designer must create an instance of...cannot because the type is declared abstract

27,942

Solution 1

I haven't seen the content at urban potato (its down) but Me and Smelch came up with a solution. Form itself inherits from an abstract class, so what they dont tell you is that its only the 1st level of inheritance that can't be abstract, the 2nd on down can.

From there its simply a matter of having an empty class in the middle and wrapping an #if debug around the forms declaration and you're good to go. Just be sure to release in release mode and design in debug mode (which is very typical).

You'll get full designer support and a real abstract base class at design (debug) and build (release) time because each time it ends up using your abstract base class.

The full explanation and answer is here

Solution 2

You can solve this using an attribute on your abstract class like the following

[TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider<MyBaseFormEf, Form>))]

This will work for every case where you need it. The AbstractControlDescriptionProvider is below

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);
    }
}

Solution 3

This worked for me with an abstract class inheriting a UserControl

public class AbstractCommunicatorProvider : TypeDescriptionProvider
{
    public AbstractCommunicatorProvider(): base(TypeDescriptor.GetProvider(typeof(UserControl)))
    {
    }
    public override Type GetReflectionType(Type objectType, object instance)
    {
        return typeof(UserControl);
    }
    public override object CreateInstance(IServiceProvider provider, Type objectType, Type[] argTypes, object[] args)
    {
        objectType = typeof(UserControl);
        return base.CreateInstance(provider, objectType, argTypes, args);
    }
}


[TypeDescriptionProvider(typeof(AbstractCommunicatorProvider))]
public abstract partial class SelectorBase : UserControl
{

///class contents 
}

I didn't need to add this to all derived classes but in your situation you may need to.

Share:
27,942
Programatt
Author by

Programatt

I am a programmer by day, and a tinkerer by night.

Updated on March 05, 2020

Comments

  • Programatt
    Programatt over 4 years

    Visual Studio complains: Warning 1 The designer must create an instance of type 'RentalEase.CustomBindingNavForm' but it cannot because the type is declared as abstract.

    Visual Studio won't let me access the Designer for the form. The class already implements all abstract methods from the CustomBindingNavForm. CustomBindingNavForm provides some functions concrete and abstract.

    Is there a way around this?

    Here is the class:

     public abstract class CustomBindingNavForm : SingleInstanceForm {     
    
            //Flags for managing BindingSource
            protected bool isNew = false;
            protected bool isUpdating = false;
    
            /// <summary>
            /// This is so that when a new item is added, it sets isNew and firstPass to true. The Position Changed Event will look for
            /// firstPass and if it is true set it to false. Then on the next pass, it will see it's false and set isNew to false.
            /// This is needed because the Position Changed Event will fire when a new item is added.
            /// </summary>
            protected bool firstPass = false;
    
    
            protected abstract bool validateInput();
            protected abstract void saveToDatabase();
    
    
            //manipulating binding
            protected abstract void bindingSourceCancelResetCurrent();
            protected abstract void bindingSourceRemoveCurrent();
            protected abstract void bindingSourceMoveFirst();
            protected abstract void bindingSourceMoveNext();
            protected abstract void bindingSourceMoveLast();
            protected abstract void bindingSourceMovePrevious();
            protected abstract void bindingSourceAddNew();
    
            public void bindingNavigatorMovePreviousItem_Click(object sender, EventArgs e) {
                if (validateInput()) {
                    bindingSourceMovePrevious();
                } else {
                    DialogResult cont = MessageBox.Show(null, "There are errors in your data. Click Cancel to go back and fix them, or ok to continue. If you continue, changes will not be saved.", "Continue?", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
                    if (cont == DialogResult.OK) {
                        if (isNew) {
                            bindingSourceRemoveCurrent();
                            isNew = false;
                        } else {
                            bindingSourceCancelResetCurrent();
                            bindingSourceMovePrevious();
                        }
                    }
                }
            }
    
            public void bindingNavigatorAddNewItem_Click(object sender, EventArgs e) {
                if (validateInput()) {
                    saveToDatabase();
                    bool temp = isUpdating;
                    isUpdating = true;
                    bindingSourceAddNew();
                    isUpdating = temp;
    
                    isNew = true;
                    firstPass = true;
                } else {
                    DialogResult cont = MessageBox.Show(null, "There are errors in your data. Click Cancel to go back and fix them, or ok to continue. If you continue, changes will not be saved.", "Continue?", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
                    if (cont == DialogResult.OK) {
    
                        if (isNew) {
                            bindingSourceRemoveCurrent();
                            isNew = false;
                        } else {
                            bindingSourceCancelResetCurrent();
                        }
    
                        bool temp = isUpdating;
                        isUpdating = true;
                        bindingSourceAddNew();
                        isUpdating = temp;
    
                        isNew = true;
                        firstPass = true;
                    }
                }
            }
    
            public void bindingNavigatorMoveFirstItem_Click(object sender, EventArgs e) {
                if (validateInput()) {
                    bindingSourceMoveFirst();
                } else {
                    DialogResult cont = MessageBox.Show(null, "There are errors in your data. Click Cancel to go back and fix them, or ok to continue. If you continue, changes will not be saved.", "Continue?", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
                    if (cont == DialogResult.OK) {
                        if (isNew) {
                            bindingSourceRemoveCurrent();
                            isNew = false;
                        } else {
                            bindingSourceCancelResetCurrent();
                        }
                        bindingSourceMoveFirst();
                    }
                }
            }
    
            public void bindingNavigatorMoveNextItem_Click(object sender, EventArgs e) {
                if (validateInput()) {
                    bindingSourceMoveNext();
                } else {
                    DialogResult cont = MessageBox.Show(null, "There are errors in your data. Click Cancel to go back and fix them, or ok to continue. If you continue, changes will not be saved.", "Continue?", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
                    if (cont == DialogResult.OK) {
                        if (isNew) {
                            bindingSourceRemoveCurrent();
                            isNew = false;
                        } else {
                            bindingSourceCancelResetCurrent();
                        }
                        bindingSourceMoveNext();
                    }
                }
            }
        }