2011-08-24 19 views
2

我有大量非常相似的用户控件。他们有很多共同的行为。我一直在使用一个基本类,它具有常见的东西,然后根据需要专门设计类。正确的架构来扩展WinForm 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 
    } 
    // ... 
} 

可以使按钮显示为baseSplitContainer的孩子,如果我做addButtonToBase()虚并手动将其添加到BaseControl的InitalizeComponent()中的生成代码中。 BaseControl的布局仍在继续,您可以在C#.Net中的构造函数中调用虚函数....

所以即使它工作,它也不是一个好的解决方案。首先,当我在VS设计器中编辑BaseControl时,IntializeComponent中对addBaseControl()的调用被移除,对于构造函数中的另一个调用虚拟函数来说,这会很危险。

我认为我需要得到基本控制的布局在导出的控制再次发生...... 我试过,但无论是做错了或者它不会工作...

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

回答

0

我想你只是想念一些东西来调用基本的init逻辑来创建控件,然后你的改变被覆盖。尝试调用它像

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

OR

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

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

当一个派生控件被构造时,总是调用基类构造函数。没有必要调用base.InitializeComponent()它也没有解决布局问题。 – meissnersd

4

原来修改基本控制布局的正确方法是重写从Control.OnLayout()

布局通话所以像

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