I was reading similar questions about overloading eventhandlers by not using eventhandlers but delegates or by calling other functions from within the eventhandler. But I really can't see how I can bind the delegate to the custom control like I am binding ButtonClick in the code below. I have a form with let's say 10 custom controls. Each custom control has 5 buttons. The way I am passing the key presses from each button of each custom control is:
This is in my custom control's cs file (GlobalDebugMonitorControl.cs)
namespace GlobalDebugMonitor
{
public partial class GlobalDebugMonitorControl : UserControl
{
public GlobalDebugMonitorControl()
{
InitializeComponent();
}
public event EventHandler ButtonClick;
private void MultiControl_Click(object sender, EventArgs e)
{
if (this.ButtonClick != null)
this.ButtonClick(sender, e);//**How Do I put here both sender and this**
}
}
}
Then all the buttons in the custom control.designer.cs have something like this:
this.openFileBTN.Click += new System.EventHandler(this.MultiControl_Click);
this.editFilePathBTN.Click += new System.EventHandler(this.MultiControl_Click);
this.delControlBTN.Click += new System.EventHandler(this.MultiControl_Click);
this.addControlBTN.Click += new System.EventHandler(this.MultiControl_Click);
this.editCompanyNameBTN.Click += new System.EventHandler(this.MultiControl_Click);
And then in my form1
namespace GlobalDebugMonitor
{
public partial class Form1 : Form
{
protected void UserControl_ButtonClick(object sender, EventArgs e)
{
Button tempButton = (Button)sender;
GlobalDebugMonitorControl tempParentControl = (GlobalDebugMonitorControl)((tempButton.Parent).Parent).Parent;
}
private void Form1_Load(object sender, EventArgs e)
{
foreach (string item in tempGlobalPaths)
{
GlobalDebugMonitorControl tempGDMcontrol = new GlobalDebugMonitorControl();
tempGDMcontrol.Name = item.Split(',')[0];
tempGDMcontrol.companyNameLBL.Text = item.Split(',')[0];
tempGDMcontrol.globalPathTXT.Text = item.Split(',')[1];
tempGDMcontrol.ButtonClick += new EventHandler(UserControl_ButtonClick);
flowLayoutPanel1.Controls.Add(tempGDMcontrol);
}
}
}
}
As you can see I create a tempButton by the sender to do some things based on which button was pressed of the 5 and by sender.parent.parent (the custom control is inside a table that is inside a flowlayout that is inside another panel etc)I finally reach the custom control that tells me which of the 10 custom controls had it's button pressed.
So the question is, is there a way to pass both the sender(button that was pressed) and the great grandfather (the custom control that owns the sender button)? I mean it works but this way I need to now how many "generations" I need to go up.
Thank you for reading me.
You could introduce your own type of EventArgs
public class CustomEventArgs : EventArgs
{
public GlobalDebugMonitorControl Control { get; set; }
public CustomEventArgs(GlobalDebugMonitorControl control)
{
this.Control = control;
}
}
and then change eventHandler to use it:
public event EventHandler<CustomEventArgs> ButtonClick;
so the calling code would be:
this.ButtonClick(sender, new CustomEventArgs(this));
and of course the implementer of the event:
protected void UserControl_ButtonClick(object sender, CustomEventArgs e)
{
Button tempButton = (Button)sender;
GlobalDebugMonitorControl tempParentControl = e.Control;
}
I'm trying to make a button that shows a message box when you click it. The button is made as a user control and it's put inside a panel container. What i want to do is when you click the button, the controls dissapear within the panel.
Code in usercontrol
public partial class UserControl1 : UserControl
{
public event EventHandler ButtonClick;
public UserControl1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//bubble the event up to the parent
if (this.ButtonClick != null)
this.ButtonClick(this, e);
MessageBox.Show("Test"); //test if the button itself is working
}
}
Code in Form
public partial class Form1 : Form
{
UserControl1 usercontrol1 = new UserControl1();
public Form1()
{
usercontrol1.ButtonClick += new EventHandler(btnIsClicked);
InitializeComponent();
}
private void btnIsClicked(object sender, EventArgs e)
{
panel1.Controls.Clear();
}
}
Having used the code above it's not working, the button works but nothing happens in the form.
I have main form and 2 usercontrols.The main form contains split container, In splitcontainer.panel1 i loaded UserControl1. In usercontrol different buttons are placed. I wants to load usercontrol2 on panel2(in main form) on button clicks which are placed inside the usercontrol1.
public partial class Form1 : Form
{
UserControl1 obj = new UserControl1();
public Form1()
{
InitializeComponent();
splitContainer1.Panel1.Controls.Add(obj);
}
}
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public event EventHandler ButtonClick;
public void button1_Click(object sender, EventArgs e)
{
}
}
On button1_Click i want to load UserControl2 on form splitcontainer panel2
You could change your UserControl1 like this:
public void button1_Click(object sender, EventArgs e)
{
if(ButtonClick != null)
ButtonClick(this, e);
}
And then in your Form1 constructor add the following code:
obj.ButtonClick += (Sender, e) =>
{
splitContainer1.Panel2.Controls.Add(obj2);
};
This should work
I am struggling in adding a dynamic and removing a user control into the form. I have a form and inside my form I have a panel which it has a static control.
What I am trying to achieved is to add the user control into the panel. Though it was easy to add but I know there is a better way out there to do this.
Adding a user control to my panel by clicking a button in the form.
private void btnadd_Click(object sender, EventArgs e)
{
UserControl1 usr = new UserControl1
pnlUI.SuspendLayout();
pnlUI.Controls.Clear();
pnlUI.Controls.Add(usr);
pnlUI.ResumeLayout(false);
}
// This one adds it and clearing the control that was already in the panel of the form.
Now, I get stacked here in removing the user control that was added and trying to display again the control that was in the panel that was been removed or cleared.
On my user control there is a back button on that back button I am trying to dispose the user control. But after that the original control is no longer there and the panel is empty already.
Any suggestions?
You could add an instance variable to your form to keep track of the previous control. This assumes that there will only ever be one control in the panel.
In your class:
private Control _previousPanelContent;
then in your method:
private void btnadd_Click(object sender, EventArgs e)
{
UserControl1 usr = new UserControl1();
pnlUI.SuspendLayout();
// check if there's already content in the panel, if so, keep a reference.
if (pnlUI.Controls.Count > 0)
{
_previousPanelContent = pnlUI.Controls[0];
pnlUI.Controls.Clear();
}
pnlUI.Controls.Add(usr);
pnlUI.ResumeLayout(false);
}
then later when you want to go back:
pnlUI.SuspendLayout();
pnlUI.Controls.Clear();
// if the previous content was set, add it back to the panel
if (_previousPanelContent != null)
{
pnlUI.Controls.Add(_previousPanelContent);
}
pnlUI.ResumeLayout(false);
Here's a simple example of the Event approach mentioned in the Comments above.
The UserControl with a "Back" event:
public partial class UserControl1 : UserControl
{
public event dlgBack Back;
private UserControl1 _previous = null;
public delegate void dlgBack(UserControl1 sender, UserControl1 previous);
public UserControl1(UserControl1 previous)
{
InitializeComponent();
this._previous = previous;
}
private void btnBack_Click(object sender, EventArgs e)
{
if (Back != null)
{
Back(this, _previous);
}
}
}
The Form then creates the UserControl and subscribes to the Event:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnAdd_Click(object sender, EventArgs e)
{
UserControl1 prevUsr = pnlUI.Controls.OfType<UserControl1>().FirstOrDefault();
UserControl1 usr = new UserControl1(prevUsr);
usr.Back += usr_Back;
pnlUI.Controls.Clear();
pnlUI.Controls.Add(usr);
}
void usr_Back(UserControl1 sender, UserControl1 previous)
{
pnlUI.Controls.Remove(sender);
if (previous != null)
{
pnlUI.Controls.Add(previous);
}
}
}
You are declaring your user control inside your button callback function (callback function is a function called at runtime when an event occurs, such as a button click etc.).
This means that the variable holding your user control is inaccessible outside it, and therefore you are not able to use it from another callback function.
Instead of doing this:
private void btnadd_Click(object sender, EventArgs e)
{
//This is not accessible outside the callback function.
UserControl1 usr = new UserControl1();
pnlUI.SuspendLayout();
pnlUI.Controls.Clear();
pnlUI.Controls.Add(usr);
pnlUI.ResumeLayout(false);
}
Try declaring a property that will hold the user control, in order to use it elsewhere:
//Declare a private property - you can adjust the access level of course,
//depending on what you need.
//You can even declare a field variable for the same cause,such as
//private UserControl _myUserControl;
//This declaration is in the class body.
private UserControl MyUserControl { get; set; }
//Your addition callback function.
private void btnadd_Click(object sender, EventArgs e)
{
//The user control is now assigned to the property.
MyUserControl = new UserControl1();
pnlUI.SuspendLayout();
pnlUI.Controls.Clear();
pnlUI.Controls.Add(MyUserControl);
pnlUI.ResumeLayout(false);
}
//Your removal callback function.
private void btnremove_Click(object sender, EventArgs e)
{
//...
//Use the property value here.
pnlUI.Controls.Remove(MyUserControl);
//...
}
I collected the solutions above (mostly the first of #Idle_Mind) I just added and adjusted some lines ; I will use his sentences:
Here's a simple example of the Event approach mentioned in the Comments above.
The UserControl with a "Back" event:
No Change here
public partial class UserControl1 : UserControl
{
public event dlgBack Back;
private UserControl1 _previous = null;
public delegate void dlgBack(UserControl1 sender, UserControl1 previous);
public UserControl1(UserControl1 previous)
{
InitializeComponent();
this._previous = previous;
}
private void btnBack_Click(object sender, EventArgs e)
{
if (Back != null)
{
Back(this, _previous);
}
}
}
The Form then creates the UserControl and subscribes to the Event:
Let take a look at commented lines
public partial class Form1 : Form
{
//prevUsr is global instead
private UserControl1 prevUsr = null;
public Form1()
{
InitializeComponent();
}
private void btnAdd_Click(object sender, EventArgs e)
{
//prevUsr is removed from here
//UserControl1 prevUsr = pnlUI.Controls.OfType<UserControl1>().FirstOrDefault();
UserControl1 usr = new UserControl1(prevUsr);
usr.Back += usr_Back;
pnlUI.Controls.Clear();
pnlUI.Controls.Add(usr);
//prevUsr is updated
prevUsr = usr;
}
void usr_Back(UserControl1 sender, UserControl1 previous)
{
pnlUI.Controls.Remove(sender);
//prevUsr is updated
prevUsr = previous;
if (previous != null)
{
pnlUI.Controls.Add(previous);
}
}
}
And, don't forget to set btnBack_Click for click of the UserControl's back button.
I hope this is helpful, it worked perfectly at my side ; I can send or share the full VS project (VS2012).
I hope it works for you,
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private int count = 0;
private LinkedList<UserControl1> lstControls = new LinkedList<UserControl1>();
private void btnAdd_Click(object sender, EventArgs e)
{
var c = new UserControl1();
if (pnlUI.Controls.Count > 0)
{
lstControls.AddLast(pnlUI.Controls[0] as UserControl1);
pnlUI.Controls.Clear();
}
c.lblTitle.Text = "Control #" + (++count).ToString();
pnlUI.Controls.Add(c);
}
private void btnBack_Click(object sender, EventArgs e)
{
if (lstControls.Last != null)
{
var lastControl = lstControls.Last.Value;
pnlUI.Controls.Clear();
pnlUI.Controls.Add(lastControl);
lstControls.RemoveLast();
}
}
}
I combine the answers of idle_mind,rdavisau and fabrice. I used rdavisau code in getting back the controls and idle_mind for the back event in the usercontrol and fabrice for his some modifications in the form.. I wish i can split the bounty into three,so I give it to idle mind..thanks all
I created a class:
class GetControls
{
private Control[] cntrl;
public Control[] Previous
{
get
{
return cntrl;
}
set
{
cntrl = value;
}
}
}
on my main form here is the revised code.
GetControls help = new GetControls();
private void btnpay_Click(object sender, EventArgs e)
{
TenderUI usr = new TenderUI(prevUsr);
usr.Back += usr_Back;
help.Previous = pnlUI.Controls.OfType<Control>().ToArray();
pnlUI.Controls.Clear();
pnlUI.Controls.Add(usr);
}
and to retrieve the controls
void usr_Back(TenderUI sender, TenderUI previous)
{
pnlUI.Controls.Remove(sender);
if (help.Previous != null)
{
foreach (Control ctr in help.Previous)
{
pnlUI.Controls.Add(ctr);
}
}
}
I have a button from a user control and want it to notify my form when it is clicked. Here is how I do it. It does not work. Can someone tell me what is wrong with it?
In user Control
public event EventHandler clicked;
public string items;
InitializedData data = new InitializedData();
ArrayList list = new ArrayList();
public DataInput()
{
InitializeComponent();
clicked+= new EventHandler(Add_Click);
}
public void Add_Click(object sender, EventArgs e)
{
items = textBox1.Text.PadRight(15) + textBox2.Text.PadRight(15) + textBox3.Text.PadRight(15);
if (clicked != null)
{
clicked(this, e);
}
}
In Form1
UserControl dataInput= new UserControl();
public void OnChanged(){
dataInput.clicked += Notify;
MessageBox.Show("testing");
}
public void Notify(Object sender, EventArgs e)
{
MessageBox.Show("FIRE");
}
Thanks
The UserControls Button Click event should be assigned to Add_Click, I don't think you want to assign the UserControl clicked event to Add_Click
Try removing clicked += new EventHandler(Add_Click); from your UserControl and set the UserControls Button Click event to Add_Click so it will trigger clicked on you Form
Example:
UserControl:
public partial class UserControl1 : UserControl
{
public event EventHandler clicked;
public UserControl1()
{
InitializeComponent();
// your button
this.button1.Click += new System.EventHandler(this.Add_Click);
}
public void Add_Click(object sender, EventArgs e)
{
if (clicked != null)
{
// This will fire the click event to anyone listening
clicked(this, e);
}
}
}
Form:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// your usercontrol
userControl11.clicked += userControl11_clicked;
}
void userControl11_clicked(object sender, EventArgs e)
{
}
}