I have a windows form called FormMain in ClientForms project. Now this(FormMain) form opens another form called FormScheduler in Scheduling project.
Now, I want to send a message back to FormMain when a button_click method event is triggered in FormScheduler.
My solution creates a circular dependency. Is there another way, like using delegates ?
Use events.
In your form FormScheduer add a button and the following code:
public event EventHandler ButtonClicked;
private void button1_Click(object sender, EventArgs e) {
if (ButtonClicked != null) {
ButtonClicked(this, EventArgs.Empty);
}
}
In your FormMain, instantiate and display your FormScheduer form like this:
var form = new FormScheduer();
// Listen for the ButtonClicked event...
form.ButtonClicked += form__ButtonClicked;
form.Show();
Your form_ButtonClicked method on FormMain will be called when the button on FormScheduler is clicked:
void form__ButtonClicked(object sender, EventArgs e) {
Console.WriteLine("clicked");
}
Related
I have 2 forms - Mainmenu form , that clicks to a registration from.
On the registration form, I have a button. I want the form to automatically click when the form is loaded. Below is what I have tried so far but it doesn't work. Any suggestions?
public Membershipform()
{
InitializeComponent();
Button_1.PerformClick();
}
The problem is that you're calling PerformClick() in the Form's constructor. At which point, the Visible property of the Button is false, causing PerformClick() to fail because in order for it to work, both the Visible and Enabled properties of the button must be true. You can confirm this by checking the source.
Your options:
Move the call to PerformClick() to the Load event of the form.
private void Membershipform_Load(object sender, EventArgs e)
{
Button_1.PerformClick();
}
Move the code in the button's Click event handler to a separate method and call that method from the constructor.
public Membershipform()
{
InitializeComponent();
DoSomething();
}
private void DoSomething()
{
// Code that was originally in Button_1_Click
}
private void Button_1_Click(object sender, EventArgs e)
{
DoSomething();
}
Call Button_1_Click directly from the form constructor:
public Membershipform()
{
InitializeComponent();
Button_1_Click(null, EventArgs.Empty);
}
Im not able to modify from my Form1 an element that belongs to Form 2.
public partial class Project : Form
{
public Form2 form = new Form2();
public Project()
{
InitializeComponent();
}
private void Project_Load(object sender, EventArgs e)
{
form.CreateControl();
}
private void buttonOpenForm2_Click(object sender, EventArgs e)
{
form.Show();
}
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
var indata = *whatever serial input data here*
bool result = Int32.TryParse(indata, out int data);
if (result) {
form.chart1.Invoke(new Action(() => { form.chart1.Series[0].Points.AddY(data); }));
}
}
Any time I press my button in order to show Form2 and its chart, an exception is raised in form.chart1.Invoke: Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
Why is this happening if i'm forcing form to do a CreateControl() ?
The error message is telling you what is wrong.
Your serial port is firing before the form2 (that holds your chart) is fully created
I guess you could check the visible flag (there are probably many others)
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
...
if(!form?.Visible)
return;
form.chart1.Invoke(...
The assumption is if its not visible, you don't want to display the data
Further reading
Order of Events in Windows Forms
Application Startup and Shutdown Events
The Form and Control classes expose a set of events related to
application startup and shutdown. When a Windows Forms application
starts, the startup events of the main form are raised in the
following order:
Control.HandleCreated
Control.BindingContextChanged
Form.Load
Control.VisibleChanged
Form.Activated
Form.Shown
I have created a form with 5 static tabs and then created 5 separate forms that load in to them at Main form load. The first of these tabs has buttons on the form that I want to link to and show the corresponding tab when clicked.
The problem I'm having is that the buttons not being on the main form but a separate form don't have the options to switch to the corresponding tab on the main form.
I have tried the tabControl1.SelectedTab = tabPage2 stumped me for a couple of days this one any help much appreciated
As I understand your question, your problem is "How to communicate the button click on the sub form to the main form".
I'd suggest to declare events in your sub forms and catch these events in your main form. So a simplified example of a sub form could look like this:
public class SubForm : Form
{
// this is the event to register with from MainForm
public event EventHandler ButtonClicked;
// thread safe event invocator (standard pattern)
protected virtual void OnButtonClicked()
{
EventHandler handler = ButtonClicked;
if (handler != null) handler(this, EventArgs.Empty);
}
// your button handler
private void button1_Clicked(object sender, Eventargs e)
{
OnButtonClicked();
}
}
And in your main form you could do the following:
public class MainForm : Form
{
private SubForm _subForm1 = new SubForm();
private SubForm _subForm2 = new SubForm();
public MainForm()
{
InitializeComponents();
// more initializatino
_subForm1.ButtonClicked += subForm1_ButtonClicked;
_subForm2.ButtonClicked += subForm2_ButtonClicked;
}
private void subForm1_ButtonClicked(object sender, EventArgs e)
{
tabControl1.SelectedTab = tabPage1;
}
private void subForm2_ButtonClicked(object sender, EventArgs e)
{
tabControl1.SelectedTab = tabPage2;
}
And you can also think about using only one someSubForm_ButtonClicked handler and infer which tab to select via the sender argument, which will be the SubForm that raised the event.
I create a event and handle it on the Form
User Control Code:
public event EventHandler ButtonClick;
private void button1_Click(object sender, EventArgs e)
{
if (this.ButtonClick != null)
this.ButtonClick(sender, e);
}
Form Code:
private Usercontrol1 sampleUserControl = new Usercontrol1();
public Form1()
{
InitializeComponent();
sampleUserControl.ButtonClick += new EventHandler(this.UserControl_ButtonClick);
}
private void UserControl_ButtonClick(object sender, EventArgs e)
{
//sample event stuff
this.Close();
Form2 F2 = new Form2();
F2.Show();
}
but the event does not firing. What must be the problem?
private Usercontrol1 sampleUserControl = new Usercontrol1();
It isn't terribly obvious exactly what button you clicked, but it won't be the button on that user control. You never added it to the form's Controls collection so it is not visible. Fix:
public Form1()
{
InitializeComponent();
this.Controls.Add(sampleUserControl);
sampleUserControl.BringToFront();
sampleUserControl.ButtonClick += new EventHandler(this.UserControl_ButtonClick);
}
With some odds that you now have two of those user controls on your form. One that you previously dropped on the form, possibly with the name "Usercontrol11". And the one you added in code. Either use the designer or write the code, doing it both ways causes this kind of trouble.
i've taken your code and compiled it and the event fired right off, so my answer is that the ButtonClick event that you created and fired in the method button1_Click isn't called because the method is not connected to the event of the button clicked for some reason.
please check that the method is called and that the event ButtonClick have been registered on the moment the method button1_Click was called. if the method was not called, you haven't registered the button1_Click method. otherwise, you might have registered to some other item
public Form1()
{
InitializeComponent();
this.Usercontrol11.ButtonClickEvent += new EventHandler(UserControl_ButtonClick);
}
private void UserControl_ButtonClick(object sender, EventArgs e)
{
//sample event stuff
this.Close();
Form2 F2 = new Form2();
F2.Show();
}
Usercontrol1 is the name of usercontrol. So when I add the usercontrol1 to form i gives me the name Usercontrol11
Im making a userControl named [File_Manager] and i was wondering if i can add a button to this custom control that i can set its job later after adding this custom control to another form .. something like
File_Manager fManager = new File_Manager();
fManager.SetFreeButtonJob( MessageBox.Show("Hello") ); // something like this.
then whenever user press that button .. the messageBox shows up.
So.. Is it possible to do that?
thanks in advance.
Sure you can. Just attach the buttons click handler to the action you pass in.
fManager.SetFreeButtonJob(() => MessageBox.Show("Hello"));
private void SetFreeButtonJob(Action action)
{
button1.Click += (s,e) => action();
}
Just note that passing in the Action breaks the encapsulation of user control though. You should probably do something like SetFreeButtonJob(Jobs.SayHello); and put the knowledge of what to do inside the control.
Create a custom event for your UserControl and fire it when your Button is clicked. You can then attach an event handler to the custom event in your Form. Or you can just raise the UserControl's Click Event when your Button is clicked.
public delegate void CustomClickEventHandler(object sender, EventArgs e);
public partial class buttonTest : UserControl
{
public event CustomClickEventHandler CustomClick;
public buttonTest()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
CustomClick(sender, e);
}
}
and in your Form
public Form1()
{
InitializeComponent();
buttonTest1.CustomClick +=new CustomClickEventHandler(userControl1_ButtonClick);
}
private void userControl1_ButtonClick(object sender, EventArgs e)
{
MessageBox.Show("Hello");
}
Or as my second option try.
private void button2_Click(object sender, EventArgs e)
{
OnClick(e);
}
and in your Form subscribe to the UserControl's Click event.
buttonTest1.Click +=new EventHandler(buttonTest1_Click);
private void buttonTest1_Click(object sender, EventArgs e)
{
MessageBox.Show("Hello Again");
}