Correct architecture to extend WinForm UserControl base classes?
I have large number of UserControls that are very similar. They share a lot of common behavior. I been using a base class that has the common stuff and then specializing the class as needed.
class BaseControl : UserControl
{
// common
}
class RedControl : BaseControl
{
// specialized
}
class BlueControl : BaseControl
{
// specialized
}
etc ...
This works fairly well until I needed to start inserting or changing the layout of the child controls contained in BaseControl. For example RedControl needs to add a Button to a particular panel of the base control. In other case I need to change the size or layout of other base child controls.
When I tried the following code, I did not see any button at run time...
public partial class RedControl : BaseControl
{
public RedControl()
{
InitializeComponent();
addButtonToBase(); // no button shows up
this.PerformLayout();
开发者_如何学JAVA }
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
}
// ...
}
I can make the button display as a child of baseSplitContainer if I make addButtonToBase() virtual and manually add it to the generated code in InitalizeComponent() of BaseControl. The layout of BaseControl was still going on and you are permitted to call virtual functions in constructors in C#.Net....
So even though it works, its not a nice solution. For one thing, when I edit BaseControl in the VS designer, the call to addBaseControl() in IntializeComponent gets removed, For another calling virtual functions in constructors feels dangerous.
I think I need to get the layout of the base control to happen again in the derived control... I tried that but either did it wrong or it wont work...
btw yes I know WPF is good at this. Cant use it because of constraints on other systems.
It turns out the correct way to modify the layout of a base control is to override the layout call from Control.OnLayout()
so something like
public RedControl()
{
//....
protected override void OnLayout(LayoutEventArgs e)
{
addButtonToBase(); // modify base layout
base.OnLayout(e);
}
}
I think you just miss something to call the base init logic to create the controls and your changes are then overriden. Try to call it like
public RedControl()
: base()
{ ... }
OR
public RedControl()
{
base.InitializeComponent();
InitializeComponent();
addButtonToBase(); // no button shows up
this.PerformLayout();
}
精彩评论