Reputation: 1886
I'm trying to write a form theme class library to adjust the form layout in a simple way for any project I'll be working on.
This is basically an idea of what it should look like:
In essence, the plugin works as follows:
// form class, which inherits the plugin class
class FormToTheme : ThemedForm
{
public FormToTheme()
{
// some code here
}
}
// plugin class itself
class ThemedForm: Form
{
public ThemedForm()
{
// some code here
}
}
Basically I set the FormBorderStyle to None, and drew the layout by code.
But now, the controls that are added can be placed over the custom titlebar, which isn't possible in a normal form if you keep the default FormBorderStyle.
So I figured that I could work around this by automatically adding the controls to the content panel, instead of the usercontrol.
So what I tried to do was this:
private void ThemedForm_ControlAdded(Object sender, ControlEventArgs e)
{
// some simple code to set the control to the current theme I'm using
e.Control.BackColor = Color.FromArgb(66, 66, 66);
e.Control.ForeColor = Color.White;
// the code where I try to place the control in the contentPanel controls array,
// and remove it from it's parent's controls array.
if (e.Control.Name != contentPanel.Name)
{
e.Control.Parent.Controls.Remove(e.Control);
contentPanel.Controls.Add(e.Control);
}
}
But when I try to add a new control in the main form as well as in the visual editor, i get the following error:
child is not a child control of this parent
So my question is: is there a way to work around this error, and move the controls from the usercontrol to the content panel?
Note that I do want this to be automated in the ThemedForm class, instead of calling methods from the main form.
EDIT:
I tried this:
http://forums.asp.net/t/617980.aspx
But that will only cause visual studio to freeze, and then I need to restart.
Upvotes: 1
Views: 2079
Reputation: 1886
I know that it is not really appropriate to answer ones own question, however the solution I came up with will take quite some explaining, which will be too much to add in my question with an edit.
So here we go:
Inside the inherited 'ThemedForm' class, I created a private variable, in order to be able to return the variable when the Controls property would be called:
private Controls controls = null;
I set the variable to null, because I need to pass variables to the class in the 'ThemedForm' class constructor. I will create a new instance of the class later on.
Then I created a class to replace the Controls property:
public class Controls
{
private Control contentPanel = null;
private ThemedForm themedform = null;
public Controls(ThemedForm form, Control panel)
{
contentPanel = panel;
themedform = form;
}
public void Add(Control control)
{
if (control != contentPanel)
{
contentPanel.Controls.Add(control);
}
else
{
themedform.Controls_Add(control);
}
}
public void Remove(Control control)
{
if (control != contentPanel)
{
contentPanel.Controls.Remove(control);
}
else
{
themedform.Controls_Remove(control);
}
}
}
I know this class holds far from all functionality of the original Controls property, but for now this will have to do, and if you like, you can add your own functionality.
As you can see in the Add and Remove methods in the Controls class, I try to determine wether the control that needs to be added is either the content panel I want to add the rest of the controls to, or any other control that needs to be added to the content panel.
If the control actually is the content panel, I add or remove it to or from the Controls property of the base class of the 'ThemedForm' class, which is a 'Form' class. Otherwise, I just add the control to the content panel's Controls property.
Then I added the Controls_Add and Controls_Remove methods to the 'ThemedForm' class, in order to be able to add or remove a control from the Controls property of the 'ThemedForm' base class.
public void Controls_Add(Control control)
{
base.Controls.Add(control);
}
public void Controls_Remove(Control control)
{
base.Controls.Remove(control);
}
They are quite self-explanatory.
In order to call the Controls.Add or the Controls.Remove methods from an external class, I needed to add a public property that hid the current Controls property, and returned the private variable that I assigned to the replacing class.
new public Controls Controls
{
get { return controls; }
}
And finally I created a new instance of the Controls class, passing the current 'ThemedForm' class, and the contentPanel control, in order to get it all to run.
_controls = new Controls(this, contentPanel);
After doing all this, I was able to 'redirect' any controls that were added to the UserControl (even inside the visual editor) to the content panel. This allowed me to use the Dock property of any control, and it would dock inside the content panel, instead of over my entire form.
This is still a little bit buggy, because inside the visual editor the docked controls still seem like they are docked over the entire form, but when running the application the result is as I wanted.
I really hope this helps anyone.
Upvotes: 3