来自抽象 base-Form 的控件在被 child 表单继承时不显示
Controls from abstract base-Form not shown when inherited by a child Form
我遵循 Juan Carlos Diaz 提供的解决方案 here
我的问题是我没有在具体 class 中看到任何抽象 class 的表单控件。我期待他们在那里,这样我就可以使用设计编辑器和具体的 class.
以下是我采取的步骤:
- 创建一个新的解决方案
- 创建一个新的 winforms 项目 (.Net 4.5.2)
- 创建一个名为
AbstractBaseForm.cs
的表单,并添加一些 hello world 逻辑:
将abstract
关键字添加到AbstractBaseForm.cs
;您的代码应如下所示:
public abstract partial class AbstractBaseForm : Form
{
protected AbstractBaseForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "Hello World";
}
}
将以下 class 添加到您的项目中:
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);
}
}
将以下属性添加到 AbstractBaseForm.cs
:
[TypeDescriptionProvider(typeof (AbstractControlDescriptionProvider<AbstractBaseForm, Form>))]
public abstract partial class AbstractBaseForm : Form
{
向项目添加第二个表单,标题为 ConcreteForm.cs
并让它继承自 AbstractBaseForm.cs
,如下所示:
public partial class ConcreteForm : AbstractBaseForm
{
public ConcreteForm()
{
InitializeComponent();
}
}
更改 program.cs 使其加载 ConcreteForm.cs
如下:
Application.Run(new ConcreteForm());
执行项目。您应该会看到 ConcreteForm.cs
加载,单击按钮会将标签更改为 "Hello World"。
关闭应用程序,然后单击 ConcreteForm.cs
,调出其设计视图。你会看到这个:
为什么我在设计视图中看不到从 AbstractBaseForm.cs
继承的控件?
添加对基本构造函数的调用
public partial class ConcreteForm : AbstractBaseForm
{
public ConcreteForm() : base()
{
InitializeComponent();
}
}
正如@hans-passant 建议的那样,删除抽象关键字。使用 abstract 关键字后,我收到以下错误:
The designer must create an instance of type
'WindowsFormsApplication1.Form1' but it cannot because the type is
declared as abstract.
我遵循 Juan Carlos Diaz 提供的解决方案 here
我的问题是我没有在具体 class 中看到任何抽象 class 的表单控件。我期待他们在那里,这样我就可以使用设计编辑器和具体的 class.
以下是我采取的步骤:
- 创建一个新的解决方案
- 创建一个新的 winforms 项目 (.Net 4.5.2)
- 创建一个名为
AbstractBaseForm.cs
的表单,并添加一些 hello world 逻辑:
将
abstract
关键字添加到AbstractBaseForm.cs
;您的代码应如下所示:public abstract partial class AbstractBaseForm : Form { protected AbstractBaseForm() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { label1.Text = "Hello World"; } }
将以下 class 添加到您的项目中:
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); } }
将以下属性添加到
AbstractBaseForm.cs
:[TypeDescriptionProvider(typeof (AbstractControlDescriptionProvider<AbstractBaseForm, Form>))] public abstract partial class AbstractBaseForm : Form {
向项目添加第二个表单,标题为
ConcreteForm.cs
并让它继承自AbstractBaseForm.cs
,如下所示:public partial class ConcreteForm : AbstractBaseForm { public ConcreteForm() { InitializeComponent(); } }
更改 program.cs 使其加载
ConcreteForm.cs
如下:Application.Run(new ConcreteForm());
执行项目。您应该会看到
ConcreteForm.cs
加载,单击按钮会将标签更改为 "Hello World"。关闭应用程序,然后单击
ConcreteForm.cs
,调出其设计视图。你会看到这个:
为什么我在设计视图中看不到从 AbstractBaseForm.cs
继承的控件?
添加对基本构造函数的调用
public partial class ConcreteForm : AbstractBaseForm
{
public ConcreteForm() : base()
{
InitializeComponent();
}
}
正如@hans-passant 建议的那样,删除抽象关键字。使用 abstract 关键字后,我收到以下错误:
The designer must create an instance of type 'WindowsFormsApplication1.Form1' but it cannot because the type is declared as abstract.