Timer from another form not stopping - c#

Architecture
___ParentForm
|___Timer
|___Panel___ChildForm
|___StopButton
I've got a ParentForm with an attached Timer and a Panel containing the ChildForm.
Problem encountered
I want to stop the ParentForm's timer from the ChildForm but the timer is never stopping.
What I've tried
// timer modifiers = Public
private void stopButton_Click(object sender, EventArgs e)
{
ParentForm parentForm = new ParentForm();
parentForm.timer.Stop();
parentForm.timer.Enabled = false;
}

Create an event in the child form and subscribe to the event in the parent form. Clicking the button in the child form raises the event. In the event handler on the parent form, stop the timer.
ParentForm.cs
public partial class ParentForm : Form
{
ChildForm childForm = null;
public ParentForm()
{
InitializeComponent();
}
private void ParentForm_Load(object sender, EventArgs e)
{
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
toolStripStatusLabel2.Text = DateTime.Now.ToString("HH:mm:ss");
statusStrip1.Refresh();
}
private void btnOpenChildForm_Click(object sender, EventArgs e)
{
if (childForm == null || childForm.IsDisposed)
{
childForm = new ChildForm();
//subscribe to events
childForm.FormClosed += ChildForm_FormClosed;
childForm.StopTimerButtonClicked += ChildForm_StopTimerButtonClicked;
childForm.Show();
}
else
{
childForm.WindowState = FormWindowState.Normal;
childForm.Activate();
}
}
private void ChildForm_FormClosed(object sender, FormClosedEventArgs e)
{
//unsubscribe from events
childForm.FormClosed -= ChildForm_FormClosed;
childForm.StopTimerButtonClicked -= ChildForm_StopTimerButtonClicked;
childForm = null;
}
private void ChildForm_StopTimerButtonClicked(object sender, bool e)
{
//stop timer
timer1.Stop();
}
}
ChildForm.cs
public partial class ChildForm : Form
{
public delegate void EventHandlerStopTimerButtonClicked(object sender, bool e);
//event that subscribers can subscribe to
public event EventHandlerStopTimerButtonClicked StopTimerButtonClicked;
public ChildForm()
{
InitializeComponent();
}
private void btnStop_Click(object sender, EventArgs e)
{
if (StopTimerButtonClicked != null)
{
//raise event
StopTimerButtonClicked(this, true);
}
}
}

Related

Replacing ShowDialog() with Show()

I have a form that is being shown using ShowDialog(), thus it is a modal window.
private void OpenForm(object sender, ItemClickEventArgs e)
{
MyForm testForm = new MyForm();
...
testForm.Enabled = true;
testForm.ShowDialog(this);
var dialogOk = testForm.DialogOK;
if(dialogOk)
{
//do some stuff 1
}
}
There is an "OK" button on the form. When OK is clicked, DialogOk is set to true. Inside MyForm class:
private void OkClick(object sender, EventArgs e)
{
// do some stuff 2
...
DialogOK = true;
Hide();
}
I need to convert this to a non-modal window. The solution seems to be to use Show() instead of ShowDialog(), but when I use Show(), the code does not stop and wait for the OK button to be clicked, so "do some stuff 1" is never called.
Using Show(), how can I keep the behavior to have "do some stuff 1" run after the OK button is clicked?
Update: Here is what I am trying now:
public partial class MyForm: XtraForm
{
public bool DialogOk;
private void OkClick(object sender, EventArgs e)
{
// do some stuff 2
...
DialogOk = true;
Close();
}
}
Method 1:
public partial class MyMainForm : XtraForm
{
private MyForm testForm;
private void OpenForm(object sender, ItemClickEventArgs e)
{
if(testForm == null)
{
testForm = new MyForm();
}
...
testForm.Enabled = true;
testForm.FormClosed += (s, a) => {
var dialogOk = testForm.DialogOk;
if (dialogOk)
{
// do some stuff 1
}
};
testForm.Show(this);
}
}
Method 2:
public partial class MyMainForm : XtraForm
{
private MyForm testForm;
private void OpenForm(object sender, ItemClickEventArgs e)
{
if(testForm == null)
{
testForm = new MyForm();
}
...
testForm.FormClosed += testForm_Closed;
testForm.Show(this);
}
private void testForm_Closed(object sender, EventArgs args)
{
var testForm = (Form)sender;
testForm.Closed -= testForm_Closed;
if (testForm.DialogResult == DialogResult.OK)
{
// do some stuff 1
}
}
}
You can handle Form.Closed event:
MyForm testForm = new MyForm();
testForm.Closed += testForm_Closed;
testForm.Show();
private void testForm_Closed(object sender, EventArgs args)
{
var testForm = (Form)sender;
testForm.Closed -= testForm_Closed;
if (testForm.DialogResult == OK)
// do some stuff 1
}
The easiest way is to move the code from OpenForm to the event handler OkClick. However, if this is not a good spot to put the code because you might want to use the same form for different tasks, you could add a handler for the FormClosed event, that is called after the form is closed and runs the code, e.g.:
private void OpenForm(object sender, ItemClickEventArgs e)
{
MyForm testForm = new MyForm();
...
testForm.Enabled = true;
testForm.FormClosed += (s, a) => {
var dialogOk = testForm.DialogOK;
if(dialogOk)
{
//do some stuff 1
}
};
testForm.Show(this);
}
You can use an async event handler tied to an TaskCompletionSource which listens and awaits the close of the form
private asyc void OpenForm(object sender, ItemClickEventArgs e) {
var source = new TaskCompletionSource<DialogResult>();
EventHandler handler = null;
handler = (s, args) => {
var form = (MyForm)s;
form.FormClosed -= handler;
source.SetResult(form.DialogResult);
}
var testForm = new MyForm();
testForm.FormClosed += handler; //subscribe
//...
testForm.Enabled = true;
testForm.Show();
var dialogOk = await source.Task;
if(dialogOk == DialogResult.Ok) {
//do some stuff 1
}
}
With that you can keep the logic in the OpenForm and allow the code to wait without blocking.
In the form when the button is clicked then all you need to do is set the dialog result and close the form.
public partial class MyForm: XtraForm {
//...
private void OkClick(object sender, EventArgs e) {
// do some stuff 2
// ...
DialogResult = DialogResult.Ok;
Cose();
}
}
This works for me, so not sure why it isn't for you (scratching head)... This form has two buttons, one which opens the same form again and another button that closes the form. The 'parent' form adds an event to the Closed event.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form1 test = new Form1();
test.FormClosed += Test_FormClosed;
test.Show();
}
private void Test_FormClosed(object sender, FormClosedEventArgs e)
{
MessageBox.Show("closed -- do something else here!");
}
private void button2_Click(object sender, EventArgs e)
{
Close();
}
}

Wait for Input in User Control

I'm trying to implement a customized exit prompt in my WinForms. (I should not be using DialogBox)
I have a User Control Object placed in my main form that is invisible and disabled by default. Clicking in a certain button I have placed on the form shows and enables the object, disabling everything in my form except the User Control.
private void btn_close_Click(object sender, EventArgs e) {
prompt1.Visible = true;
prompt1.Enabled = true;
disableControls();
//Wait for a button to be pressed in prompt1
//Make an action based on a button pressed.
//closeApp returns a boolean
if (!prompt1.closeApp)
{
prompt1.Visible = false;
prompt1.Enabled = false;
enableControls();
}
else
{
Application.Exit();
}
}
Here's my code at the prompt object:
public partial class Prompt : UserControl
{
bool exit;
public bool closeApp
{
get{return exit;}
}
public Prompt()
{
InitializeComponent();
}
private void btn_yes_Click(object sender, EventArgs e)
{
exit = true;
}
private void btn_no_Click(object sender, EventArgs e)
{
exit = false;
this.Hide();
}
}
What I want to do is wait for a button to be pressed in my prompt object before proceeding to the next line in the btn_close_Click().
What should I do? Is there a better way to implement this?
Add events to your usercontrol then handle those events on your main form.
In your usercontrol:
public event EventHandler<EventArgs> ExitCancelled;
public event EventHandler<EventArgs> ExitApplication;
private void btn_yes_Click(object sender, EventArgs e)
{
ExitApplication?.Invoke(this, EventArgs.Empty);
}
private void btn_no_Click(object sender, EventArgs e)
{
ExitCancelled?.Invoke(this, EventArgs.Empty);
}
Handle the events on your form:
public void prompt1_ExitApplication(object sender, EventArgs e)
{
Application.Exit();
}
public void prompt1_ExitCancelled(object sender, EventArgs e)
{
prompt1.Hide();
enablecontrols();
}

How to send all events of a child control to its parent control (custom control)?

I have one custom control containing three child controls (Panel with PictureBox control and Label) and I want to send all events of a child controls to its parent control (custom control).
I know there are lots of answers regarding this problem, but I cannot figure out it with a simple solution.
Here is my example
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
UserControl1 uc1 = new UserControl1();
this.Controls.Add(uc1);
}
}
public partial class UserControl1 : UserControl
{
public PictureBox ChildPictureBox { get; set; }
public UserControl1()
{
PictureBox pictureBox1 = new PictureBox();
pictureBox1.Size = new Size(150, 150);
pictureBox1.BackColor = Color.Red;
pictureBox1.Click += PictureBox1_Click;
this.Controls.Add(pictureBox1);
ChildPictureBox = pictureBox1;
this.Click += UserControl1_Click;
}
private void UserControl1_Click(object sender, EventArgs e)
{
MessageBox.Show("User control click");
}
private void PictureBox1_Click(object sender, EventArgs e)
{
MessageBox.Show("pic clicked");
}
}
The following code is the example, here UserControl1 has PictureBox and Panel and their click events are hooked into MainForm i-e MyForm as named. You can modify it as per your requirements.
UserControl1.cs
public partial class UserControl1 : UserControl
{
public delegate void PictureBoxClickHandler(object sender, EventArgs e);
public event PictureBoxClickHandler PictureBoxClick;
public delegate void PanelClickHandler(object sender, EventArgs e);
public event PanelClickHandler PanelClick;
public delegate void PictureBoxDoubleClickHandler(object sender, EventArgs e);
public event PictureBoxDoubleClickHandler PictureBoxDoubleClick;
public delegate void PictureBoxMouseMoveHandler(object sender, MouseEventArgs e);
public event PictureBoxMouseMoveHandler PictureBoxMouseMove;
public UserControl1()
{
InitializeComponent();
}
private void pictureBox1_Click(object sender, EventArgs e)
{
if (PictureBoxClick != null)
{
PictureBoxClick(sender, e);
}
}
private void panel1_Click(object sender, EventArgs e)
{
if (PanelClick != null)
{
PanelClick(sender, e);
}
}
private void pictureBox1_DoubleClick(object sender, EventArgs e)
{
if (PictureBoxDoubleClick != null)
{
PictureBoxDoubleClick(sender, e);
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (PictureBoxMouseMove != null)
{
PictureBoxMouseMove(sender, e);
}
}
}
MyForm.cs
public class MyForm : Form
{
public MyForm()
{
InitializeComponent();
var userControl1 = new UserControl1();
Controls.Add(userControl1);
userControl1.PictureBoxClick += userControl1_PictureBoxClick;
userControl1.PanelClick += userControl1_PanelClick;
userControl1.PictureBoxDoubleClick+=userControl1_PictureBoxDoubleClick;
userControl1.PictureBoxMouseMove+=userControl1_PictureBoxMouseMove;
}
private void userControl1_PanelClick(object sender, EventArgs e)
{
//Click: Panel on userControl1
}
private void userControl1_PictureBoxClick(object sender, EventArgs e)
{
//Click: PictureBox on userControl1
}
private void userControl1_PictureBoxMouseMove(object sender, MouseEventArgs e)
{
throw new NotImplementedException();
}
private void userControl1_PictureBoxDoubleClick(object sender, EventArgs e)
{
throw new NotImplementedException();
}
}
EDIT:
public partial class UserControl1 : UserControl
{
public PictureBox ChildPictureBox { get; set; }
public UserControl1()
{
InitializeComponent();
ChildPictureBox = pictureBox1;
}
//----
}
Now in form
public class MyForm : Form
{
public MyForm()
{
InitializeComponent();
PictureBox pictureBox = userControl1.ChildPictureBox;
//now work with pictureBox here
pictureBox.Click += pictureBox_Click;
}
private void pictureBox_Click(object sender, EventArgs e)
{
throw new NotImplementedException();
}
}
I think you can do this, but you should know that uncommon events cannot be linked to other controls.
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
foreach (Control control in this.Controls)
{
control.Click += new EventHandler(control_Click);
}
}
private void control_Click(object sender, EventArgs e)
{
this.UserControl1_Click(sender, e);
}
private void UserControl1_Click(object sender, EventArgs e)
{
}
}

How notify that form that executed a thread in other class?

I have two forms called frm1 and frm2:
public partial class frm1 : Form
{
private WebMethods wm;
public frm1()
{
InitializeComponent();
}
private void button_Click(object sender, EventArgs e)
{
wm = new WebMethods();
wm.test();
}
}
public partial class frm2 : Form
{
private WebMethods wm;
public frm2()
{
InitializeComponent();
}
private void button_Click(object sender, EventArgs e)
{
wm = new WebMethods();
wm.test();
}
}
now I have a class called WebMethods :
class WebMethods
{
private BackgroundWorker backgroundWorker;
public void stop(){
backgroundWorker.CancelAsync();
}
public void test()
{
if (backgroundWorker.IsBusy != true)
{
this.backgroundWorker = new BackgroundWorker();
backgroundWorker.WorkerSupportsCancellation = true;
backgroundWorker.DoWork += new DoWorkEventHandler(_PostRequest);
backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_PostRequestComplet ed);
backgroundWorker.RunWorkerAsync();
}
}
private void _PostRequest(object sender, DoWorkEventArgs e)
{
// ...
}
private void _PostRequestCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// ...
}
}
now I want when backgroundworker thread finished and _PostRequestCompleted event executed, it notify that form that executed test() method.
for example if frm1 executed test() method at end _PostRequestCompleted() method notify frm1 that thread was finished. for example _PostRequestCompleted executes a method in frm1 after finishing thread.
but I dont know how do this ??
Declare an event in WebMethods class and register it in your form classes.
class WebMethods
{
public event EventHandler PostRequestCompletedEvent;
private void _PostRequestCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// ...
if (PostRequestCompletedEvent != null)
{
PostRequestCompletedEvent(this, new EventArgs());
}
}
}
Now register this event in your form classes.
public partial class frm1 : Form
{
private WebMethods wm;
public frm1()
{
InitializeComponent();
}
private void button_Click(object sender, EventArgs e)
{
wm = new WebMethods();
wm.PostRequestCompletedEvent += wm_PostRequestCompletedEvent;
wm.test();
}
void wm_PostRequestCompletedEvent(object sender, EventArgs e)
{
// notify frm1 that thread was finished
}
}
public partial class frm2 : Form
{
private WebMethods wm;
public frm2()
{
InitializeComponent();
}
private void button_Click(object sender, EventArgs e)
{
wm = new WebMethods();
wm.PostRequestCompletedEvent += wm_PostRequestCompletedEvent;
wm.test();
}
void wm_PostRequestCompletedEvent(object sender, EventArgs e)
{
// notify frm2 that thread was finished
}
}

Delegate and event

I have 2 forms.
Form1:
public partial class Panel1
{
public void ShowExport(object sender, EventArgs e)
{
.......
}
}
Form2:
public partial class Panel2
{
public delegate void ShowExportReport(object sender, EventArgs e);
public event ShowExportReport ShowExportClicked;
private void buttonExport_Click(object sender, RoutedEventArgs e)
{
if (ShowExportClicked != null)
{
ShowExportClicked(sender, new EventArgs());
}
}
}
When I click button -
button.Click = buttonExport_Click
How can I call Panel1.ShowExport() from Panel2.buttonExport_Click?
In the Panel1 you have to subscribe the event:
pnl2.ShowExportClicked += new ShowExportReport(ShowExport);
You need to assign the handler for the event ShowExportClicked in Panel 1 class to the Panel 2 class object.
public partial class Panel1
{
Panel2 pnl2;
public Panel1()
{
pnl2 = new Panel2();
pnl2.ShowExportClicked += new ShowExportReport(ShowExport);
}
public void ShowExport(object sender, EventArgs e)
{
.......
}
}
pnl2.ShowExportClicked += ShowExport;
Create your event on Form1. and listen to the event in Form2.
Form1:
public event EventHandler ShowExportChanged;
private void ShowExportChanged()
{
var handler = ShowExportChanged;
if(handler == null)
return;
handler(this, EventArgs.Empty);
}
public void ShowExport(object sender, EventArgs e)
{
ShowExportChanged();
}
Form2:
pnl1.ShowExportChanged+= new OnShowExportChanged(ShowExportChanged);
How can I call Panel1.ShowExport() from Panel2.buttonExport_Click?
By passing (only the necessary) information from form1 when instantiating form2.
Form1.cs:
void ShowForm2_Click()
{
var form2 = new Form2();
form2.ShowExportClicked += ShowExport;
form2.Show();
}
Now from Form2 you can simply call ShowExport on button click.

Categories