正确的架构扩展WinForm UserControl基类?

时间:2011-08-24 11:53:12

标签: c# winforms user-controls dynamic-usercontrols

我有大量非常相似的UserControl。他们有很多共同的行为。我一直在使用具有常见内容的基类,然后根据需要对类进行专门化。

class BaseControl : UserControl 
{
   // common
}  

class RedControl : BaseControl
{
   // specialized
}

class BlueControl : BaseControl
{
   // specialized
}
等等......

在我需要开始插入或更改BaseControl中包含的子控件的布局之前,这非常有效。例如,RedControl需要将Button添加到基本控件的特定面板。在其他情况下,我需要更改其他基本子控件的大小或布局。

当我尝试以下代码时,我在运行时没有看到任何按钮......

public partial class RedControl : BaseControl
{
  public RedControl()
  {
    InitializeComponent();

    addButtonToBase();  // no button shows up 
    this.PerformLayout();
  }
  void addButtonToBase()
  {
    Button button  = new Button();
    button.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)));
    button.Location = new System.Drawing.Point(3, 3);
    button.Size = new System.Drawing.Size(23, 23);
    button.Text = "My Button";

    baseSplitContainer.Panel1.Controls.Add(button); // protected child control in base
  }
  // ...
}
如果我将addButtonToBase()虚拟化并手动将其添加到BaseControl的InitalizeComponent()中生成的代码中,可以使按钮显示为baseSplitContainer的子节点。 BaseControl的布局仍在继续,你可以在C#.Net中的构造函数中调用虚函数。

所以即使它有效,它也不是一个好的解决方案。首先,当我在VS设计器中编辑BaseControl时,IntializeComponent中对addBaseControl()的调用被删除, 对于另一个调用构造函数中的虚函数感觉很危险。

我想我需要在派生控件中再次发生基本控件的布局... 我试过了,但要么做错了要么不行......

是的,我知道WPF擅长这一点。由于其他系统的限制,不能使用它。

2 个答案:

答案 0 :(得分:4)

事实证明,修改基本控件布局的正确方法是覆盖Control.OnLayout()的布局调用

类似

public RedControl()
{
    //....
    protected override void OnLayout(LayoutEventArgs e)
    {
        addButtonToBase(); // modify base layout
        base.OnLayout(e);
    }
}

答案 1 :(得分:0)

我认为您只是错过了调用基本初始化逻辑来创建控件的内容,然后您的更改将被覆盖。尝试将其称为

public RedControl()
: base()
  { ... }

OR

public RedControl()
  {
    base.InitializeComponent();
    InitializeComponent();

    addButtonToBase();  // no button shows up 
    this.PerformLayout();
  }