Making a function wait for an event C# - c#

I have a class that creates an instance of a form with several buttons. I have a function in this class which is meant to wait for the user to click one of the buttons and return different values depending on which button was pressed. I've read some of the stuff on using anonymous delegates for this, but I'm not sure how I would determine which specific button was pressed. My original approach was to create a custom event that takes the button number as parameter, and tacking an event handler onto that from my class, but again I am not sure how I would have that function return anything once I get into a delegate.
Is there any straightforward way of doing this?
PM

Assuming WinForms, there are a few approaches you could take. You could expose each button as a property on your form class and have the class the creates the form subscribe to the Click event for each button. For example,
In the Form class:
public class MyForm : Form
{
// form initialization, etc, etc.
public Button Button1
{
get { return button1; }
}
}
In the class that creates the form:
public class MyClass
{
public Form CreateForm()
{
var form = new MyForm();
form.Button1.Click += HandleButton1Clicked;
return form;
}
private void HandleButton1Clicked(object sender, EventArgs e)
{
// do whatever you need to do when Button1 is clicked
}
}
Alternatively, you could add a ButtonClicked event to the Form and determine which button was pressed that way. The form would subscribe to each of its button's Click events and fire ButtonClicked with button as the sender.
I'd probably go with the former since it would avoid having to write an if statement to determine which button was pressed.
Edited to adapt to the workflow in comments:
In that case, what you can do is have the Form take care of some of the details for you. For example, have the form record which button was pressed. If you show the form as a modal dialog, that will by design block the function that's created the form until it is dismissed.
public class MyForm : Form
{
// form initialization, etc, etc.
private Button button1;
private Button button2;
public MyForm()
{
InitializeComponent();
button1.Click += HandleButtonClicked;
button1.DialogResult = DialogResult.OK;
button2.Click += HandleButtonClicked;
button2.DialogResult = DialogResult.OK;
}
private void HandleButtonClicked(object sender, EventArgs e)
{
ButtonClicked = sender as Button;
}
public Button ButtonClicked
{
get; private set;
}
}
Calling code:
public class MyClass
{
public int GetValue()
{
var form = new MyForm();
if(form.ShowDialog() == DialogResult.OK) // this will block until form is closed
{
// return some value based on form.ButtonClicked
// adjust method's return type as necessary
}
else
{
// do something if the user closed the form without
// clicking on one of the buttons
}
}
}
Note that the HandleButtonClicked event handler is the same for both buttons, since the form is just storing which button was clicked.

Related

How to make a form click a button when loaded?

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);
}

How do I access checkbox on another form?

I've just made two forms and I have two checkboxes, I want they to copy eachother (if the checkBox in Form1 is checked, the checkBox in Form2 is checked)
I dont have a code for this but I can give you my Form1 name And Form2 name
Form1: MainUI
Form2: Settings
You need to fire an event from one form and handle it on the other form.
You'll need an event args class to carry the state of the checkbox:
public class CheckEventArgs : EventArgs
{
public bool Checked { get; set; }
}
Then on your form that will be sending it's check state you'll need an event (let's assume that the Settings form will send it's checkbox state to the MainUI form) so Settings will need this adding:
public event EventHandler<CheckEventArgs> CheckboxChanged;
And on the CheckedChanged event of the checkBox you will fire the event:
public void checkBox1_CheckedChanged(object sender, EventArgs e)
{
CheckboxChanged?.Invoke(this, new CheckEventArgs() { Checked = checkBox1.Checked });
}
On the form you want to receive the result from you'll need to handle that event (this code goes on MainUI):
public Form1()
{
InitializeComponent();
Form2 Settings = new Form2();
Settings.CheckboxChanged += settings_CheckboxChanged;
}
public void settings_CheckboxChanged(object sender, CheckEventArgs e)
{
checkBox1.Checked = e.Checked;
}
I would suggest that you don't use this to send in both directions without some modifications. Otherwise you will end up in an infinite loop firing the event back and forth between the two forms. Just use it in one direction and you'll be fine.

How to send a TextBox value to a variable in the parent form in C#?

I have an aboutBox control ("settings") that has a textBox in it. When the user presses the save button on this settings I want it to save the string from the textBox, pass it to a variable in the main form, close the settings box and then press a button in the main form.
How would this be done?
Thank you!
A solution using public methods. I have used controls with default names, see the comments for what these controls are related to.
Your Main.cs form :
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Mainform : Form
{
public Mainform()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
new About(this).ShowDialog(); // pass main form to about form and show it a showdialog
}
// Public textbox updating method
public void textupdatert(string input)
{
textBox1.Text = input; // textBox1 is the textbox we need to update in Main form
}
}
}
Your About.cs form :
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class About : Form
{
private Mainform mymainform; // Holds main form instance
// Contructor is updated to take the instance of Main Form
public About(Mainform mainform)
{
InitializeComponent();
mymainform = mainform;
}
private void button1_Click(object sender, EventArgs e)
{
mymainform.textupdatert(textBox1.Text); // Update Parent form's'textBox1
this.Close(); // Close about form and Exit
}
}
}
This should work :)
this is a sample code on how you would do it, you can add an event handler for the save button when your main start or if you use VisualStudio, double click on the Save button from your designer and it will create the event handler for you, but to add it manually at the start of the form,
In your main form,
private void settingsButton_Click(object sender, EventArgs e)
{
settingsBox box = new settingsBox();
DialogResult result = box.ShowDialog();
//* check if the result to see if you did not cancel the save.
//* if the user clicked on save
String textVar = box.GetMyAboutText();
}
This is in your settings form
String textVar = null; //* define global in your settingsBox;
public settingsBox()//* constructor
{
settingForm.Click += new System.EventHandler(myAboutSaveButton_Click);
}
//*add the myAboutSaveButton_Click to handle the event
private String myAboutCtlSaveButton_Click(object sender, EventArgs e)
{
textVar = myTextBox.Text;
myAboutCtl.Dispose();
}
private void GetMyAboutText()
{
return textVar;
}
Add a property in FormSettings to return the TextBox value.
public string SomeText
{
get { return textBox1.Text; }
}
Also, set the DialogResult = OK property to the Apply button, it will close the form dialog after press the button.
Usage:
using (var form = new FormSettings())
{
if (form.ShowDialog() == DialogResult.OK)
{
var text = form.SomeText;
//do something
}
}
You can try as below:
string txtBoxVal=TextBox.txt;
you can pass the textbox value using parameterized constructor of parent form.
call the parameterized constructor of parent form like
parentForm pf=new ParentForm(txtBoxVal)
In the parent form write a constructor as below:
string val; //globalVariable in the parent class
public ParentForm(string txtVal){
val=txtVal; // textbox value is assigned to val that you can use as your needs // in the class
}
Hope this helps, Thanks
First thought is to create an event in the form where you press the save button and raise this event when this button is clicked. You can listen to this event from your parent form and perform needed actions from there

How to reach and set a control's property outside of a Form?

I am really new to programming and currently working on a C# Windows Forms application.
The problem is the following:
I have a Form with different objects and controls like: tabpages, textboxes, timers, etc .
I also have a UserControl form which I load into one of the main Form's tabpages.
I would like to write a code into the UserControl , how can I manipulate element properties of the main Form.
For example: when I click on a button on the UserControl form It sets the main Form's timer.Enabled control to true.
It is possible to do this, but having the user control access and manipulate the form isn't the cleanest way - it would be better to have the user control raise an event and have the hosting form deal with the event. (e.g. on handling the button click, the form could enable/disable the timer, etc.)
That way you could use the user control in different ways for different forms if need be; and it makes it more obvious what is going on.
Update:
Within your user control, you can declare an event - In the button click, you raise the event:
namespace WindowsFormsApplication1
{
public partial class UserControl1 : UserControl
{
public event EventHandler OnButtonClicked;
public UserControl1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
EventHandler handler = OnButtonClicked;
// if something is listening for this event, let let them know it has occurred
if (handler != null)
{
handler(this, new EventArgs());
}
}
}
}
Then within your form, add the user control. You can then hook into the event:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
userControl11.OnButtonClicked += userControl11_OnButtonClicked;
}
void userControl11_OnButtonClicked(object sender, EventArgs e)
{
MessageBox.Show("got here");
}
}
}
You may want to rethink what it is you are trying to accomplish. However, to answer your question, it can be done.
The best way to do it is to make a property in your UserControl called MainForm:
public Control MainForm {
get;
set;
}
Then, in your MainForm's Load event, set the property to itself:
userControl1.MainForm = this;
Finally, in your user control, set the MainForm's timer:
protected button_click(object sender, EventArgs e)
{
timerName = "timer1";
EnableTimer(timerName);
}
private void EnableTimer(timerName)
{
var timer = MainForm.Controls.FirstOrDefault(z => z.Name.ToLower().Equals(timerName.ToLower());
if (timer != null)
{
((Timer)timer).Enabled = true;
} else {
// Timer was not found
}
}
This is very simple. It's called events. On the user control you would expose an event with a EventHandler for the form to subscribe to.
public partial class MyUserControl : UserControl
{
/// You can name the event anything you want.
public event EventHandler ButtonSelected;
/// This bubbles the button selected event up to the form.
private void Button1_Clicked(object sender, EventArgs e)
{
if (this.ButtonSelected != null)
{
// You could pass your own custom arguments back to the form here.
this.ButtonSelected(this, e)
}
}
}
Now that we have the user control code we'll implement it in the form code. Probably in the constructor of the form you'll have some code like below.
MyUserControl ctrl = new MyUserControl();
ctrl.ButtonSelected += this.ButtonSelected_OnClick;
Finally in the form code you'll have a method that subscribed to the event like the below code that will set the Timer enabled to true.
private void ButtonSelected_OnClick(object sender, EventArgs e)
{
this.Timer1.Enabled = true;
}
And that's how you allow an event on a user control on a form set an object on the form.
You can set the timer1.Modifiers property to "internal" and access it with an instance to Form1:
form1.timer1.Enabled = true;
You need to have an instance of your class Form1, not the class itself. For example:
// INVALID
Form1.timer1.Enabled = true;
// VALID
var form1 = Form1.ActiveForm;
form1.timer1.Enabled = true;
But this is not a very clean way to do this, you would rather use events as described in NDJ's answer.
You need to put the below code,
(`userControl11.OnButtonClicked += userControl11_OnButtonClicked;`)
in a separate file in Visual Studio. The other file is called 'Form1.Designer.cs', and can be found in the Solution Explorer pane under
Form1 >> Form1.cs >> Form1.Designer.cs.
Hope this helps!

passing data between two forms using properties

I am passing data between 2 windows forms in c#. Form1 is the main form, whose textbox will receive the text passed to it from form2_textbox & display it in its textbox (form1_textbox).
First, form1 opens, with an empty textbox and a button, on clicking on the form1_button, form2 opens.
In Form2, I entered a text in form2_textbox & then clicked the button (form2_button).ON click event of this button, it will send the text to form1's textbox & form1 will come in focus with its empty form1_textbox with a text received from form2.
I am using properties to implement this task.
FORM2.CS
public partial class Form2 : Form
{
//declare event in form 2
public event EventHandler SomeTextInSomeFormChanged;
public Form2()
{
InitializeComponent();
}
public string get_text_for_Form1
{
get { return form2_textBox1.Text; }
}
//On the button click event of form2, the text from form2 will be send to form1:
public void button1_Click(object sender, EventArgs e)
{
Form1 f1 = new Form1();
f1.set_text_in_Form1 = get_text_for_Form1;
//if subscribers exists
if(SomeTextInSomeFormChanged != null)
{
SomeTextInSomeFormChanged(this, null);
}
}
}
FORM1.CS
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public string set_text_in_Form1
{
set { form1_textBox1.Text = value; }
}
private void form1_button1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.Show();
f2.SomeTextInSomeFormChanged +=new EventHandler(f2_SomeTextInSomeFormChanged);
}
//in form 1 subcribe to event
Form2 form2 = new Form2();
public void f2_SomeTextInSomeFormChanged(object sender, EventArgs e)
{
this.Focus();
}
}
Now, in this case I have to again SHOW the form1 in order to automatically get the text in its textbox from form2, but I want that as I click the button on form2, the text is sent from Form2 to Form1, & the form1 comes in focus, with its textbox containing the text received from Form2.
I know this is a (really) old question, but hell..
The "best" solution for this is to have a "data" class that will handle holding whatever you need to pass across:
class Session
{
public Session()
{
//Init Vars here
}
public string foo {get; set;}
}
Then have a background "controller" class that can handle calling, showing/hiding forms (etc..)
class Controller
{
private Session m_Session;
public Controller(Session session, Form firstform)
{
m_Session = session;
ShowForm(firstform);
}
private ShowForm(Form firstform)
{
/*Yes, I'm implying that you also keep a reference to "Session"
* within each form, on construction.*/
Form currentform = firstform(m_Session);
DialogResult currentresult = currentform.ShowDialog();
//....
//Logic+Loops that handle calling forms and their behaviours..
}
}
And obviously, in your form, you can have a very simple click listener that's like..
//...
m_Session.foo = textbox.Text;
this.DialogResult = DialogResult.OK;
this.Close();
//...
Then, when you have your magical amazing forms, they can pass things between each other using the session object. If you want to have concurrent access, you might want to set up a mutex or semaphore depending on your needs (which you can also store a reference to within Session). There's also no reason why you cannot have similar controller logic within a parent dialog to control its children (and don't forget, DialogResult is great for simple forms)

Categories