C#继承在运行时设置了变量的用户控件

时间:2019-01-25 20:30:08

标签: c# .net winforms inheritance reference

我有一个主要形式,可以充当许多不同用户控件的“向导”。我有一个具有相对基本操作的用户控件,并且我试图创建一个继承此基本用户控件的新用户控件。

但是,基本用户控件具有包含主窗体的变量(因此,用户控件可以访问主窗体中的向导控件功能)。当我创建一个新的“继承的用户控件”时,设计器会抱怨未将对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出现“对象引用未设置为对象实例”错误行。

任何对此的帮助将不胜感激。希望这对您有足够的信息,以便您了解我正在尝试做的事情。

谢谢。

1 个答案:

答案 0 :(得分:1)

您共享的代码在运行时和设计时均不起作用。

您正在尝试在mainForm.exampleString的构造函数中使用BaseControl,而mainForm将在创建BaseControl的实例后立即分配。

在这种情况下,特别是当您希望获得设计时支持时,可以从ISupportInitialize界面派生并覆盖BeginInitEndInit

示例

以下控件实现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的属性。接口应包含您希望控件的父级具有的方法或属性。然后以某种形式实现接口。然后,在运行时或设计时删除控件的实例后,将表单分配给属性。