子窗体继承时未显示来自抽象基窗体的控件
Posted
技术标签:
【中文标题】子窗体继承时未显示来自抽象基窗体的控件【英文标题】:Controls from abstract base-Form not shown when inherited by a child Form 【发布时间】:2015-06-29 20:45:47 【问题描述】:我正在关注 Juan Carlos Diaz here提供的解决方案
我的问题是我没有看到任何抽象类的表单控件显示在具体类中。我希望他们在那里,以便我可以将设计编辑器与具体类一起使用。
以下是我采取的步骤:
-
创建新的解决方案
创建一个新的 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";
将以下类添加到您的项目中:
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
继承的控件?
【问题讨论】:
您是否检查以确保您正在重载 InitializeComponent() 这似乎是最有可能开始的地方。 (并且您没有使用在 ConcreteForm 中生成的新版本 @Rootix 你的意思是覆盖?InitializeComponent
是 IDE 生成的部分类的私有方法。它不是虚拟的,子类无法访问。然而,当子类的默认构造函数被调用时,它将被自动调用。
Hmya,你需要停止将枪对准你的脚并扣动扳机。设计者需要能够创建基类的实例。您可以通过重定向类型来伪造它,但是当然可以,您将获得 Form 类的行为。它没有任何控件。删除 abstract 关键字,继续你的生活。
@HansPassant:我认为你超出了我的想象。假设我在基类中单击按钮时调用以下方法: public virtual string GetMessage() return "Hello World"; 然后在子类中假设我执行以下操作: public override string GetMessage() return "Goodbye World!"; -> 根据您的建议,我将无法做到这一点,实际上将无法编译。我在您的建议中遗漏了什么?
没有。你唯一可能做错的事情就是不去尝试。
【参考方案1】:
添加对基础构造函数的调用
public partial class ConcreteForm : AbstractBaseForm
public ConcreteForm() : base()
InitializeComponent();
正如@hans-passant 建议的那样,删除 abstract 关键字。使用 abstract 关键字,我收到以下错误:
设计者必须创建一个类型的实例 'WindowsFormsApplication1.Form1' 但它不能因为类型是 声明为抽象。
【讨论】:
谢谢汉斯和本。效果很好,我仍然可以使用虚拟/覆盖。我的错误就在我耳边:我认为我需要使用抽象类来使用虚拟/覆盖关键字。以上是关于子窗体继承时未显示来自抽象基窗体的控件的主要内容,如果未能解决你的问题,请参考以下文章