我有一个主要形式,可以充当许多不同用户控件的“向导”。我有一个具有相对基本操作的用户控件,并且我试图创建一个继承此基本用户控件的新用户控件。
但是,基本用户控件具有包含主窗体的变量(因此,用户控件可以访问主窗体中的向导控件功能)。当我创建一个新的“继承的用户控件”时,设计器会抱怨未将对main的引用设置为该对象的实例。创建基本用户控件的实例时,我会在运行时设置对MainForm的引用。
有没有办法使这项工作有效?下面是一些简化的代码,演示了我的问题。
MainForm.cs:
public partial class MainForm : Form
{
public string exampleString = "From MainForm";
public MainForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
BaseControl base = new BaseControl();
base.mainForm = this;
{
}
BaseControl.cs
public partial class BaseControl : UserControl
{
public MainForm mainForm { get; set;}
public TestPanel()
{
InitializeComponent();
string needed = mainForm.exampleString; //Object reference not set to an instance of an object here
}
}
因此,当我尝试创建一个通过Solution -> Add -> New Item -> Inherited User Control
继承BaseControl并选择BaseClass的用户控件时,设计者抱怨string needed = mainForm.exampleString
出现“对象引用未设置为对象实例”错误行。
任何对此的帮助将不胜感激。希望这对您有足够的信息,以便您了解我正在尝试做的事情。
谢谢。
答案 0 :(得分:1)
您共享的代码在运行时和设计时均不起作用。
您正在尝试在mainForm.exampleString
的构造函数中使用BaseControl
,而mainForm
将在创建BaseControl
的实例后立即分配。
在这种情况下,特别是当您希望获得设计时支持时,可以从ISupportInitialize
界面派生并覆盖BeginInit
和EndInit
。
示例
以下控件实现ISupportInitialize
。如果在运行时将控件的实例拖放到窗体上,它将尝试查找父窗体,如果是MainForm
,则尝试使用MainForm
的公共成员:
using System.ComponentModel;
using System.Windows.Forms;
public class MyControl : Control, ISupportInitialize
{
public void BeginInit()
{
}
public void EndInit()
{
var parent = this.FindForm() as MainForm;
if (parent != null)
{
//Access to MainForm members
}
}
}
这只是一个示例,显示了如何使用ISupportInitialize
。实际上,依赖于特定类型的父窗体不是一个好主意。正如Jimi的comment中所提到的,一个更好的主意是依靠接口。例如,您可以在控件中拥有ISomeInterface
的属性。接口应包含您希望控件的父级具有的方法或属性。然后以某种形式实现接口。然后,在运行时或设计时删除控件的实例后,将表单分配给属性。