2015-05-06 75 views
0

我有动态加载(并销毁)不同类型的用户控件到需要的表单上的代码。用户控件使用其父级的属性将某些值加载到控件中,如文本框和复选框。问题是,在该行:从孩子访问ParentForm并确保添加孩子

activeControl = new userControl1(params...); 

我的构造函数显然会尝试还不存在装载场(它们属于父窗体),因为它没有被添加到父窗体,直到在userControl1创建后。

我试着用用户控件的ParentChanged事件来解决这个问题,所以它在加载字段之前一直等到它的父对象被设置。这里的问题是,当我销毁userControl1并创建一个userControl2时,父级更改并尝试从null ParentForm(我原本的确切问题)中加载字段。

是否有解决此问题的首选方法?显然,我可以添加类似

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

到ParentChanged事件或类似的规定。但是,这感觉既优雅也不安全。我俯瞰一些事件或完成这一首选方式?

+0

经常在事件检查null是一个好主意(不错的想法)。在InitializeComponent()事件触发期间,必须被忽略。这些假事件期间列表框和组合框的行索引为-1,并且在事件处理程序中检查索引> = 0是正常的。 – jdweng

+0

你从“ParentForm”访问的实际内容是什么?如果您将'ParentForm'强制转换为其他子类型,通常在用户控件内部访问父表单并不是一个好主意。 –

回答

0

虽然不一定是坏的检查null引用和转移代码acco (例如,不要试图引用缺失的对象),这里更好的方法是将你的UserControl类与父母分开。

也就是说,这些UserControl类根本不应该有任何意识到他们的父表单类型。否则就是否定OOP的一个主要优点:代码重用。使用您当前的设计,即使让它在没有崩溃的情况下工作,除非在此特定父级表单类型的上下文中,否则您将永远无法使用这些UserControl对象。

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

你应该做的是通过公共属性暴露UserControl状态,然后允许父表单根据需要初始化这些状态。

这里是一个非常简单的例子(我省略了设计师创建的代码…我认为你可以从现场的名字我的意思推断):

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,说明你的问题,我无法提供比上面更详细的代码示例,如果这似乎不能解决您的问题,请对其进行编辑,以便提供更多详细信息,包括更好的代码示例)。