web-dev-qa-db-ja.com

型が抽象として宣言されているため、設計者は... cannotのインスタンスを作成する必要があります

Visual Studioの文句:警告1デザイナーはタイプ 'RentalEase.CustomBindingNavForm'のインスタンスを作成する必要がありますが、タイプが抽象として宣言されているため作成できません。

Visual Studioでは、フォームのデザイナーにアクセスできません。このクラスは、CustomBindingNavFormのすべての抽象メソッドをすでに実装しています。 CustomBindingNavFormは、具体的で抽象的な関数をいくつか提供します。

これを回避する方法はありますか?

クラスは次のとおりです。

 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();
                }
            }
        }
    }
36
Malfist

アーバンポテト(ダウン)のコンテンツは見たことがありませんが、私と Smelch が解決策を思いつきました。 Form自体は抽象クラスを継承しているので、彼らが教えてくれないのはそれだけです抽象化できない第1レベルの継承、第2レベルの継承は可能です。

そこからは、真ん中に空のクラスを置き、フォーム宣言の周りに#if debugをラップするだけで、準備は完了です。必ずリリースモードでリリースし、デバッグモードで設計してください(これは非常に一般的です)。

設計(デバッグ)およびビルド(リリース)時に、完全な設計者サポートと実際の抽象基本クラスを取得できます。これは、そのたびに抽象基本クラスが使用されるためです。

完全な説明と答えはここにあります

29
Allen Rice

これは、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 
}

これをすべての派生クラスに追加する必要はありませんでしたが、状況によっては追加する必要があるかもしれません。

0
Kim

次のような抽象クラスの属性を使用してこれを解決できます

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

これは、必要なすべての場合に機能します。 AbstractControlDescriptionProviderは以下のとおりです

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