event Action<> --> reference null when using modal dialog - c#

I have two forms - frm_Main and frm_Threshold. The threshold form contains a trackbar.
All I need to do is to open the frm_Threshold from the frm_Main and if the trackbar changes trigger an event in the frm_Main.
I have found the solution (see the code) that seems to work, however, only if the frm_Threshold is called as a modal dialog from the frm_Main.
frm_Threshold code:
//event to pass value of threshold if changed onto another form
public event Action<int> ThresholdValueChanged;
//trackbar value changed
private void trackBarThreshold_ValueChanged(object sender, EventArgs e)
{
//changing value in the textbox
textBoxThreshold.Text = trackBarThreshold.Value.ToString();
//assignig value to the event to pass onto another form
ThresholdValueChanged(trackBarThreshold.Value);
}
frm_Main code:
private void toolStripButtonThreshold_Click(object sender, EventArgs e)
{
frm_Threshold formThreshold = new frm_Threshold();
formThreshold.ThresholdValueChanged += new Action<int>(Threshold);
formThreshold.ShowDialog(); // if changed to .Show() throws exception
formThreshold.ThresholdValueChanged -= new Action<int>(Threshold);
}
private void Threshold(int value)
{
// do something
}
In case I call the frm_Threshold form using the Show() method, null reference exception on the
public event Action<int> ThresholdValueChanged
is thrown (in the frm_Threshold).
Any idea how to solve the issue? Thanks!

Delete this line:
formThreshold.ThresholdValueChanged -= new Action<int>(Threshold);
If you just call the form using .Show() you immediately remove your event again.
By the way, you don't need this line in any case.

Related

Return value without close the window wpf

I want to have a return value from my WPF window without close it.
I have an DLL with WPF usercontrol inside, I call it from my DLL code.
I have to call it, it returns me datas, then I send it datas.
But I don't want to create two different instance of the same window.
My code :
MP.UserControl1 a = new MP.UserControl1();
a.ShowDialog();
if (a.DialogResult.HasValue && a.DialogResult.Value == true)
{
a.Hide();
InitialDatas = a.inputData;
}
else
return 0;
Then I elaborate InitialDatas
And now I want to call a method inside my "a", and show it again, without create a new window.
Code :
a.SetValue(result, off1, InitialDatas);
a.ShowDialog();
I got error message : Cannot set visibility or call Show, ShowDialog or EnsureHandle after a window has been closed
Is it possible to solve?
I would solve this with an event model. You could do the following:
Create an event in the Form
Create an event handler in the caller
Subscribe to the event and do your logic
The called form:
namespace MyApplication
{
public delegate void MyEventHandler(object source, EventArgs e);
public class MyForm : Form
{
public event MyEventHandler OnInitialData;
private void btnOk_Click(object sender, EventArgs e)
{
OnInitialData?.Invoke(this, null);
}
}
}
In your other Form:
MP.UserControl1 a = new MP.UserControl1();
a.OnInitialData += UCA_OnInitialData;
private void UCA_OnInitialData(object sender, EventArgs e)
{
MP.UserControl1 a = sender as MP.UserControl1;
a.SetValue(result, off1, a.inputData);
}
a.ShowDialog();
As the error message states, you cannot close the window and then open it again.
Instead of closing a window you could hide it by calling the Hide() method and then showing it again by calling the Show() method.
But since the ShowDialog() method doesn't return until the window has been closed, this won't work for a dialog window though. If you require a modal window, you will have to create a new instance of the window and open this one. This shouldn't really be an issue though.
So I guess the answer to your question is simply no. You cannot re-open a closed dialog window.

Best way to handle passing of Control.Checked state between forms

It's been a while since I've worked with Windows Forms applications. I have a Checkbox on the Main form and, based upon a certain condition, if the Second form needs to be opened to request additional data from the user, how should I pass (or get) back a message to the Main form from the Second form so I can tell whether or not it's okay to Check or Uncheck the Checkbox?
From what I can remember, I could use something like Pass by ref. Or is there a better way to accomplish this?
Since you are showing the child form as a dialog, and the parent form doesn't need it until the form as closed, all you need to do is add a property with a public getter and private setter to the child form, set the value in the child form whenever it's appropriate, and then read the value from the main form after the call to ShowDialog.
One way to do this would be to use an event.
In your child form, declare an event to be raised upon specific user interaction, and simply "subscribe" to this event in your main form.
When you instantiate and call you child form, you'd do like this:
private void button1_Click(object sender, EventArgs e)
{
Form2 frm = new Form2();
frm.MyEvent += frm_MyEvent;
frm.ShowDialog();
frm.MyEvent -= frm_MyEvent;
}
private void frm_MyEvent(object sender, EventArgs e)
{
textBox1.Text = "whatever"; //just for demo purposes
}
In your child form, you declare the event and raise it:
public event EventHandler MyEvent;
private void button1_Click(object sender, EventArgs e)
{
if (MyEvent!= null)
MyEvent(this, EventArgs.Empty);
}
Hope this helps

How to sync up to different events in Winforms

If I have a button which does something and also a double-click event on a data grid which I want to do the same thing, what is the best way to ensure that only one function has to be maintained?
Apart from doing the following, is there any fancy C# way to indicate that two events are to do the same thing?
void button1_Click(...) { MyFunction(); }
void dataGrid1_DoubleClick(...) { MyFunction(); }
void MyFunction() { // do stuff }
I suppose that you are talking about a DataGridView (WinForms) so the signature of the event DoubleClick in the DataGridView and the signature of Click event on a button control is the same.
(An EventHadler). In this case you can simply set the same method using the form designer or manually bind the event
dataGridView1.DoubleClick += new EventHandler(MyFunction);
button1.Click += new EventHandler(MyFunction);
Of course the MyFunction method should match the expected signature of an EventHandler
private void MyFunction(object sender, EventArgs e)
{
// do your work
}
Reviewing my answer after a few minutes I wish to add:
If you find yourself in a situation in which you need to differentiate between the controls using the sender object (like Control c = sender as Control; if (c.Name == "someName") ) I really suggest you to return to the first idea. Call a common method but keep the EventHandler separated for each control involved.
Using VS, in the form's designer view You can set the procedure You want to call to each control's each event in the control's properties window.
image
Just to add to what Steve said, you will want to bind these events to your function manually in the Load event of your form, instead of using the events under the lightning bolt in the properties window in the designer, like so:
private void Form1_Load(object sender, EventArgs e)
{
button1.Click += MyMethod;
dataGridView1.DoubleClick += MyMethod;
}
void MyMethod(object sender, EventArgs e)
{
//Do Stuff
}
Also, declaring a new instance of the EventHandler class has been redundant since Anonymous methods were introduced to C#, you can just point the event directly at the method as shown above.

How to perform automatic button click on Windows Form based on a Parameter? C#

I created a Windows Application with a form and few buttons on it. I need to fire the button click event automatically some times based on the parameter value passed to the application.
static class SensexPrediction
{
static void Main(string[] Args) <---- Modified this so accepting arguments.
{
Application.Run(new Sensex_Prediction_Form(Args)); <--- Passing Args to Form.
}
}
Below is the Code for Sensex_Prediction_Form method.
public Sensex_Prediction_Form(String[] Args)
{
InitializeComponent();
if (Args.Length != 0) //There is atleast one argument.
{
this.Invoker = Args[0]; <-----Invoker is the name of the data member of the class.
}
}
Now on form load if Invoker == "X" i need to perform button1_Click event code. For that i wrote the following...
private void Sensex_Prediction_Form_Load(object sender, EventArgs e)
{
if(Inovker == "x")
{
predict_butn.performclick();
}
}
But click is not happening automatically even though argument passed is X.
What i couldn't understand is the button name in the solution explorer is predict_butn but when i click on the button the event code is in a function named button1_click. Is this the reason?
Please help. Thanks.
After the suggestions i separated the event code and actual logic in a separate method named prediction.
private void Sensex_Prediction_Form_Load(object sender, EventArgs e)
{
if (Invoker == "Scheduler")
{
prediction();
}
}
And i initialized the data variable of the class with Scheduler as below..
public string Invoker = "Scheduler";
Even then when i load the form the method is not being invoked.
As suggested i corrected the connection between button name and even method name etc.
thank q
Suprisingly..(for me :-))
if (Invoker == "Scheduler")
{
MessageBox.Show("Testing");
prediction();
MessageBox.Show("OK");
}
Testing message is getting executed but after that it just displays the form. so what could be the reason?
Understood the issue..I am getting an exception object reference not set..because i have a line that says
ActiveForm.Text = "Sensex Prediction System ";
At this point form has not been loaded so it can't set the text.
------> Now the issue is how to call a method automatically after loading the form? because the method will have code that will modify the form while executing.
Got it...using the "shown" event for the form able to do what i wanted. Thanks.
Promote the code within button1_click to a method. Then once the form is loaded and if the parameter match your filter, call the method.
private void Button1_Click(object sender, EventArgs e)
{
DoSomething();
}
private void Sensex_Prediction_Form_Load(object sender, EventArgs e)
{
if(Inovker == "X")
{
DoSomething();
}
}
private void DoSomething()
{
...
}
Extract the code out of the button event into it's own method that is called in the button click. Now you just need to call that new extracted method instead of trying to invoke a ui button click.
First you can use Environment.GetCommandLineArgs() instead of passing the args to the constructor of the form.
Second you may assign the wrong event handler to the click. reassign the predict_butn.Click to its correct event handler instead of the current one which is button1_click
Double click button to generate event handler(for example button1_Click(object sender, System.EventArgs e)), and then you want to trigger that method just call button1_Click(null, null)
Of course better solution is to create one function with your logic and then call that function in button click event and when Invoker == "X".
First of all, you're not checking whether Invoker == 'X', but Invoker == 'x'. This may be part of the problem. Comparing strings with == is not good practice, however. You should use
if (Invoker.Equals('X', StringComparison.InvariantCulture))
Is the action performed if you click the button with your mouse? If so, the problem is not the event handler.
If it is not performed, the event handler and the button's event are not connected. You can check in the button's properties whether the event handler is attached to the button's click event.
What happens if you double-click the button in the designer? Is a new event handler created? If so, move the code from button1_click to the new event handler and delete the button1_click event handler.
Event handlers and control events are not automatically associated. You need to do this in the control's properties.

c# trying to get an event to fire when a different window closes

I have one form that has an option to open another (dialogue). I want an event to fire when the second window closes. The first form is named frmMain() the other is frmAddEmployee(). Heres what I have:
in frmMain()
//create and open the second window
public void (object sender, EventArgs e)
{
frmAddEmployee addEmp = new frmAddEmployee();
addEmp.ShowDialogue();
}
//create event to handle addEmp being closed
public void addEmp_Closing(object sender, EventArgs e)
{
PopulateEmployeeList();
}
I'm not sure the event is being recognized as an event. What am I doing wrong?
Events in C# have to be registered manually - the C# compiler will not automatically register method as an event handler based just on the name of the method. You need:
frmAddEmployee addEmp = new frmAddEmployee();
addEmp.Closing += addEmp_Closing; // Register event handler explicitly
addEmp.ShowDialogue();
Automatic registration of events is done in ASP.NET and Visual Basic has Handles clause, but in C#, you need to use the += operator to specify that some method should be called when an event occurs.
Assuming ShowDialogue means ShowDialog, then it shows the form modally and you don't need an event handler:
//create and open the second window
public void (object sender, EventArgs e)
{
frmAddEmployee addEmp = new frmAddEmployee();
addEmp.ShowDialog();
PopulateEmployeeList();
}
If you don't show the second form modally, then you can hook up the event handler before showing the form like this:
public void (object sender, EventArgs e)
{
frmAddEmployee addEmp = new frmAddEmployee();
addEmp.FormClosed += AddEmpClosed;
addEmp.Show();
}
private void AddEmpClosed(object sender, FormClosedEventArgs e)
{
PopluateEmployeeList();
}
There is Closing and Closed events which you can register for on the Form. You are registered for neither, unless your registration is taking place somehwere else?
Before you call addEmp.ShowDialog() you need to set your method to handle the Closing event:
frmAddEmployee addEmp = new frmAddEmployee();
addEmp.Closing += addEmp_Closing;
addEmp.ShowDialogue();

Categories