从子进入ParentForm并确保添加子进程

时间:2015-05-06 17:24:43

标签: c# winforms events user-controls

我有代码可以根据需要动态加载(并销毁)不同类型的用户控件到表单上。用户控件使用其父级的属性将某些值加载到控件(如文本框和复选框)中。问题在于:

activeControl = new userControl1(params...);  

我的构造函数显然会尝试加载尚不存在的字段(它们属于父窗体),因为在创建userControl1之前它尚未添加到父窗体中。

我尝试使用用户控件的ParentChanged事件解决此问题,因此它会等到其父项在加载字段之前设置为止。这里的问题是当我销毁userControl1并创建一个userControl2时,父更改并尝试从null ParentForm加载字段(我原来的确切问题。

有解决这个问题的首选方法吗?显然,我可以添加类似

的内容
if(this.ParentForm == null) { return; }  

到ParentChanged事件或那些行。但这既不优雅也不安全。我是否忽略了一些事件或首选方式来实现这一目标?

1 个答案:

答案 0 :(得分:0)

虽然检查null引用并相应地转移代码(例如,不尝试引用丢失的对象)并不一定是坏的,但更好的方法是将UserControl类与它们分离。父母。

也就是说,这些UserControl类根本不应该了解其父表单类型。否则就是否定OOP的一个主要好处:代码重用。使用您当前的设计,即使您在不崩溃的情况下使用它,您也无法使用这些UserControl对象,除非在此特定父表单类型的上下文中。

您今天可能认为,没关系,您永远不会想在任何其他环境中使用它们。但未来很难预测。例如,您可能决定要在父表单上使用仍应使用这些相同UserControl对象的变体。

您应该做的是通过公共属性公开UserControl状态,然后允许父表单根据需要初始化它们。

这是一个非常简单的例子(我省略了Designer创建的代码......我假设您可以从字段名称推断出我的意思):

partial class UserControl1 : UserControl
{
    /* ... */

    public bool IsMyFlagChecked
    {
        get { return checkBox1.Checked; }
        set { checkBox1.Checked = value; }
    }

    /* ... */
}

partial class ParentForm : Form
{
    /* ... */

    private void SomeMethodThatAddsUserControl1()
    {
        UserControl1 uc1 = new UserControl1;

        uc1.IsMyFlagChecked =
            this.SomeParentFormPropertyUserControl1UsedToReferenceDirectly;
        // other initialization for uc1...

        Controls.Add(uc1);
    }

    /* ... */
}

(请注意,如果没有a good, minimal, complete code example说明您的问题,我无法提供比上述更详细的代码示例。如果这似乎无法解决您的问题,请编辑它,以便它提供了更多细节,包括更好的代码示例。)