I've a class which is in a nutshell:
class MyPanel
{
Panel p_panel; //declaring all the elements I need
CheckBox cb_choice;
RadioButton rb_nagy, rb_kicsi;
TextBox tb_db;
public Panel getPanel() {
create(); //creating all the elements I need, then putting them all in the created Panel.
customize(); //setting the panel's size, and the other control's locations within the panel.
return p_panel; //so if I call this method from an other class, this method will return a panel with all the controls inside.
In the other class, I've a list of Panels all of which have been created with the above method.
The layout is done, and it works neatly, I can add as many as I want to the screen. but now I want to add some function to these controls. For example, I want all the radiobuttons disabled unless the checkbox is enabled.
So how can I add a check changed event to all the checkboxes that are in the list of panels?
It seems like you just want to know how to dynamically add EventHandlers to your controls!?
It can be done like this:
cb_choice.CheckedChanged += cb_choice_CheckedChanged;
or if you want to be more explicit (both ways work the same).
cb_choice.CheckedChanged += new EventHandler(cb_choice_CheckedChanged);
And define a handler method:
private void cb_choice_CheckedChanged(object o, EventArgs args)
{
//add code to enable/disable radiobuttons
}
Related
I'm french, so sorry for my bad english... But I hope that you will help me ;)
I'm developing a soft in c# with lot of information store in DB, like information about people.
I want display these information with a beautiful UI, like that :
For that, I created :
a first panel in Visual
a class for create sub panel dynamically
I make a loop and for each person, I call a method "createPanel" with the information of each person, and these sub panels created are added to the parent panel. The ID of each person is store in the "tag" parameter of the sub panel.
All work fine, but I don't really know how to add event in each sub panel.
As you can see in the link above, the user can click on a bookmark, or a icon for show a menu (the round with 3 point = icon "menu").
My question is how to add event for each sub panel dynamically ? For example I want display a menu for each sub panel when I click on the icon "menu", get the id store in the "tag" of the sub panel, and show a new form for manage information.
Thx for your help, I can add my code if necessary :)
Make a own user control for the panels you want to display containing all the controls from the toolbox you need.
public partial class MyControl : UserControl
{
...
}
In "MyControl" you define events for all things that can happen and must be handled externally of the control. Same as e.g. "SelectedIndexChanged" for combobox.
Your control class would then look like this:
public partial class MyControl : UserControl
{
public event EventHandler<MyImportantEventA> OnImportantThingHappend;
//Event-Invoker
protected virtual void OnOnImportantThingHappend(MyImportantEventA e)
{
OnImportantThingHappend?.Invoke(this, e);
}
}
//Data of your event. Customize as you like/need.
public class MyImportantEventA : EventArgs
{
public string Message { get; set; }
}
When you add your control dynamically, bind to the event(s) of your control:
myUserControl.OnImportantThingHappend += DoSomethingWithEvent;
Things the control can handle it self, don't need to be exposed as events.
E.g.:
"Close" may be something that must be handled externally. You need to remove the control, rearange you controls etc.
"Show Details" probably is something that can be handled completely inside of your control. Your control shows a message box or a fancy tooltip.
I have a UserControl that is dynamically added to a FlowLayoutPanel. In that same UserControl I have a button to remove itself if the user wants it, obviously at runtime. To eliminate I mean not only to eliminate that tight button, but also the full UserControl that contains the button.
The code of when the UserControl are added dynamically at the moment is as follows:
private void agregaUC() {
UserControl1 UC = new UserControl1();
aux += 1;
UC.Tag = aux.ToString();
flowLayoutPanel2.Controls.Add(UC);
}
The code to eliminate this is on the side of the form, that is, where the UserControl are being added. The button event to remove the UserControl is thrown by code through the operator + =, then there I write the suggestions that you give me.
EDIT: Based on the sample of code you've added, I've modified the below code to work better with what you are looking for. You need to find out how to access the Tag of the control you're trying to remove.
Since you don't have a reference, then you should make sure that the .Tag property can be found, because then you can do something like
foreach (Control c in flowLayoutPanel2.Controls) {
if (c.Tag == "Aux") {
flowLayoutPanel2.Controls.Remove(c);
c.Dispose();
break;
}
}
EDIT
Reading through all the comments everywhere, it seems like this is what's happening. There is a UserControl, inside that user control is a Button (Delete) and the button's Click event is subscribed to by the window, and it's in this event handler that we're trying to remove the UserControl from flowLayoutPanel2
Based on these assumptions, your function should look like this:
void UserControl_Delete_Click(object sender, EventArgs e)
{
Button Delete = (Button)sender;
UserControl UC = (UserControl)Delete.Parent;
flowLayoutControl2.Controls.Remove(UC);
UC.Dispose();
}
This is assuming a lot about the internal structure of everything, as I don't have the code to confirm this will work. It will get you a long ways down the path, though, and should only need a little tweaking based on the actual structure of the UserControl.
You can try something like that.
this.Parent.Controls.Remove(this);
Control.Parent Property.
Remark: Setting the Parent property value to null removes the control from the Control.ControlCollection of its current parent control.
So
this.Parent = null;
Edit
The code is intended to be called from within the user control itself.
I have a form containing a flowlayoutpanel, and a user control A is added to the panel. In the constructor of user control A, a pointer to the same flowlayoutpanel is passed, so that user control A creates another user control B in the same flowlayoutpanel. The problem is that user control B is first added, then A.
Form1.cs
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void addBtn_Click(object sender, EventArgs e)
{
flowLayoutPanel1.Controls.Add(new Graphic1(this.flowLayoutPanel1));
}
}
Graphic1.cs
public partial class Graphic1 : UserControl
{
public Graphic1(FlowLayoutPanel flowPointer)
{
InitializeComponent();
flowPointer.Controls.Add(new Graphic2());
}
}
Graphic2.cs is just a label
problem is that Graphic2.cs is added before Graphic1.cs in the panel
I see three possible solutions:
If the constructor of control A receives the flow layout panel, have control A add itself to the flow layout panel, then add its additional controls.
Instead of adding the additional control in the constructor of control A, add a method such as InitializeLayout to control A. You can invoke that method after adding control A to the flow layout panel, and that method could then add any additional controls to the flow layout panel.
Capture any changes to the Parent property of control A (not sure whether that is possible; that depends on the GUI toolkit you are using) and add the additional controls when the parent of control A has changed.
I have a windows form and i dont want to make any other windows forms just one windows form and different user controls how can i change between user controls for example hide one and show the other user control programmatically ?
private void Btt_info_Click(object sender, EventArgs e)
{
Frm_Main frm_main = new Frm_Main();
frm_main.Controls["panel1"].Controls.Clear();
UC_Info uc_info = new UC_Info();
frm_main.Controls["panel1"].Controls.Add(uc_info);
}
i added this but it doesnt work
Add a container control (if I remember correctly, there's a containers section in the toolbox?), like a panel. Create usercontrols for what you want to dynamically switch around. So make like a 'HomePage' usercontrol and a 'LoginPage' usercontrol. Dynamically add the usercontrol that you want to display to the container. WHen you want, remove it from the container and add a different usercontrol:
Panel myPanel = new Panel();
LoginPage ctlLoginPage = new LoginPage();
HomePage ctlHomePage = new HomePage();
//add the loginpage to the panel first
myPanel.Controls.Add(ctlLoginPage);
...do stuff...
//remove whatever control is currently in the Panel
myPanel.Controls.Clear();
//add the other control, the HomePage control instead now
myPanel.Controls.Add(ctlHomePage);
..do other stuff...
I usually do it this way so you leave your form itself open to add common controls and stuff that might be shared between your different 'pages'.
EDIT: Note that I normally would add the panel in the designer and not create it dynamically in the code. This was just an example.
EDIT: The interaction between your mainform and usercontrols can be handled in a few different ways, and I am not saying that any of these is the correct method.
You create a static property for your Panel on the Mainform, so that
you can always access it to swap your controls around.
In this example I'll also add a static method for it
enum PanelControlsEnum {HomePage, LoginPage};
public static Panel MyContainerPanel {get;set;}
public static void SwitchPanelControls(PanelControlsEnum selControl){
..put your switch panels code here..
}
Then inside your usercontrol you call a predefined method, something like:
MainForm.SwitchPanelControls(PanelControlsEnum.HomePage);
Another method is to bind the button click event on your mainform
instead of inside the form.
Like This:
HomePage ctlHomePage = new HomePage();
ctlHomePage.Click += MyClickEvent;
myPanel.Controls.Add(ctlHomePage)
...
private void MyClickEvent(object sender, RoutedEventArgs e)
{
..switch user control code here...
}
Create a method that returns a UserControl object. Then put conditions in that method as to which control you want to load at a specific condition and then in your main form code.
UserControl control = GetControlFromMyMethod();
form1.Controls.Add(control);
where 'control' is the returned control from your method.
To remove the existing one you have to loop through the form1.Controls and find out the control and call 'Remove'.
Update:
Mike C has a better idea of adding a panel and loading your desired control on the panel as then it's easy to remove your control and you then don't have to loop through the forms controls to find it and then remove it.
Try this:
this.Controls.Clear();
usercontrol load = new usercontrol ();
this.Controls.Add(load);
load.Show();
you could try this it will definitely help you as it did helped me a lot it short and straight to the point hope that will help
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:
http://www.beaverdistrict.nl/form_layout.png
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.
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.