3

Hello Everyone!

I am somehow what new to coding and stumbled across a problem. I managed to find a solution myself but I am of certain there are better solutions for it!
I will try to descripe my problem as good as my bad english skills allow me to and my solution right after. The point is, I would like to know if there is any solution in generel since my solution seems to be very specificly suited for this case only.
Okay folks, here we go!

Program description

The Program itself is set up by three Forms, the main form being a "control centre" or menu so to say, the other two being timers displayed by labels, as you can see here. The blue Timer is incremending while the green one does the opposite.

The moment I open the program the two timer forms open aswell, I need them even though they are not running. Obviously, I use the FormMain_Load Method in order to display them:

private void FormMain_Load(object sender, EventArgs e)
    {
        Form1 timerUp = new Form1();
        timerUp.Show();
        Form2 timerBreak = new Form2();
        timerBreak.Show();
    }

The Question

Now, exsactly that is my problem! The second someone clicks on one of those two start buttons I would like to start the timer on the form (since i put the timer for each timer on its own form). But if i use

private void buttonStart_Click(object sender, EventArgs e)
    {
        timerUp.timer1.Start();
    }

in order to accsess the "timerUp" Variable I can not access the local variable "Form1 timerUp" inside FormMain_Load. It says "Variable does not exist in the current context".

I would be awfully glad if someone knew about a possible solution to simply turn on the timer on the already open form from another class.

My solution

As already spoilert, I managed to find a solution even though I am not happy about its setup.
In order to maintain my solution, the two timers start the second the forms open, for example inside Form1 (first timer):

private void Form1_Load(object sender, EventArgs e)
    {
        timer1.Start();
    }

However, there is some logic behind it. I've set up some public static booleans inside mainForm and let them be change by clicking on buttons. For example:

public partial class FormMain : Form
{
    public static bool timer1 = false;
    public static bool timer2 = false;
    ....

    private void buttonStart_Click(object sender, EventArgs e)
    {
        timer1 = true;
    }
}

Now, inside Form1 again, I've added a few if-statements to check for those booleans. Just like that:

private void timer1_Tick(object sender, EventArgs e)
    {
        if (FormMain.timer1)
        {
            ....
        }
    }

Obviously, that solution does have some performance issues:

  • Timers are always running
  • If-statements have to be checked each tick

Even though those are basicly of no matter for such a small program as I made, I am eager to learn how to adress such a problem the proper way.
Thanks in advance for any response!

Sepheraton
  • 51
  • 7
  • You can keep `timerUp` and `timerBreak` in `FormMain` fields. But what will happen if the user closes one of those forms? – Ivan Stoev Dec 13 '15 at 12:19
  • Instead of using booleans, you could expose the `timer` in each sub-form. So then you'd have `buttonStart_Click(...) { timerUp.timer.Start(); }`. Or, a more encapsulated approach: define a method in the subforms called `startTimer`, and then in your main form run `timerUp.StartTimer();` – Rob Dec 13 '15 at 12:20

3 Answers3

1

As per my comment, try something like this:

public class MainForm
{
    Form1 timerUp = new Form1();
    Form2 timerBreak = new Form2();
    private void MainForm_Load(object sender, EventArgs e)
    {
        timerUp.Show();
        timerBreak.Show();
    }

    private void buttonStart_Click(object sender, EventArgs e)
    {
        timerUp.StartTimer();
    }
}

public class Form1
{
    private Timer _timer = new Timer();
    public void StartTimer()
    {
        _timer.Start();
    }
}
Rob
  • 26,989
  • 16
  • 82
  • 98
1

As far as I understand your question, it should be sufficient to move the variables timerUp and timerBreak out of the Form_Load event handler of the Main form to class level, e.g.:

public class FormMain
{
    // Class level fields
    private Form1 timerUp = new Form1();
    private Form2 timerBreak = new Form2();

    private void FormMain_Load(object sender, EventArgs e)
    {
        timerUp.Show();
        timerBreak.Show();
    }

    // Use the class level fields wherever you need to
    private void buttonStart_Click(object sender, EventArgs e)
    {
        timerUp.timer1.Start();
    }

    // Dispose of the class-level fields when MainForm is disposed
    protected void Dispose(bool disposing)
    {
        base.Dispose(disposing);
        if (disposing)
        {
            timerUp.Dispose();
            timerBreak.Dispose();
        }
    }
}
Markus
  • 20,838
  • 4
  • 31
  • 55
1

Before listing possible solutions, I strongly recommend learning more about the MVC and/or MVVM (Usually used in WPF) architectural patterns. They will guide you how to distribute the responsibilities between classes and views in a GUI application. It will be a steep learning curve but it will be worth it in the end.

  1. Move timerUp and timerBreak variables directly in the class level of MainForm. That way, you will be able to access them by using a reference to your main form.

     Form1 timerUp;
     Form2 timerBreak;
    
    
      private void MainForm_Load(object sender, EventArgs e)
      {
         timerUp = new Form1();
         timerBreak = new Form2();
         timerUp.Show();
         timerBreak.Show();
      }
    
  2. If you feel that the timer controls of the two forms will be referenced throughout your application, you could keep references to them in your main form.

  3. You can use events to notify the timers that they should start/stop. These events could either be in your MainForm, or preferably in a separate class. This separate class would also contain the model of your timers (Properties such as Time, State, etc) and would notify your timers through the property change notification event. This is heavily used in MVVM.

Orestis P.
  • 805
  • 7
  • 27
  • I had a look into MVC but I am super confused. I am glad I have some basic knowledge about C# without any knowledge about ASP.NET thus far unfortionaly, but nearly everything I can find deals with that. Is there anything you could recommend for C# in generel? I catched the basic idea (formating the code in a special way to make it easier) but unfortionally didn't understand a thing. – Sepheraton Dec 13 '15 at 14:53
  • There are some examples and information that target WinForms specifically. [link](http://www.codeproject.com/Articles/613682/Your-first-program-using-MVC-pattern-with-Csharp-W) [link](http://stackoverflow.com/questions/122388/how-would-you-implement-mvc-in-a-windows-forms-application) [link](http://www.codeproject.com/Articles/613682/Your-first-program-using-MVC-pattern-with-Csharp-W). You can also look for the MVP pattern, I've been told it's more appropriate for WinForms. – Orestis P. Dec 13 '15 at 15:03