title: Using a windows forms timer to trigger a method from in a different class
body: <p>Apologies if there are already answers out there for this, but I've dug a lot and found little.</p>
  
  <p>I'm trying to implement a watchdog system on a C# .NET 4.5 Windows Forms Application.  Basically, I have a form with various buttons, text displays, etc, that connects to an external device.  I have a timer on the main form that should check the device for changes every 250ms or so.</p>
  
  <p>I've lumped all MainPage form code, including the timer, into one class, and the code for the external device into its own class that inherits from MainPage.  Trouble is, I want to be able to have the timer's Tick() function call a method from the Device class.  Here's simplified code:</p>
  
  <pre><code>namespace MyApplication
  {
      public partial class MainPage : Form
      {
          public MainPage()
          {
              InitializeComponent();
          }
  
          public static void SetTextBox(string Message)
          {
              Textbox_Status.Text = Message;
          }
  
          private void timer1_Tick(object sender, EventArgs e)
          {
              Device.DeviceCheck();
          }
      }
  
      public class Device : MainPage
      {
          public void DeviceCheck()
          { 
              //Do other stuff here
              SetTextBox("Some text");
          }
      }
  }
  </code></pre>
  
  <p>Naturally, I can't call <code>Device.DeviceCheck</code> from within the timer because it's not static.  However, if I declare DeviceCheck static, I now get an error that <code>Textbox_Status</code> is not static.  If I try to declare it static, Visual Studio gets VERY mad at me!</p>
  
  <p>Originally, I had dumped everything into the same class and it all worked fine, but that is very ugly code.  Is there a better way?</p>
  
  <p>EDIT: The extra snag = more than one thing in the form that needs to be changed by DeviceCheck()</p>
  
  <p>So what I left out of the simplified code: in addition to the SetTextBox() method, I also have a method in the form that sets some indicators, based on information from DeviceCheck:</p>
  
  <pre><code>    public void SetImages(string Image)
      {
          switch(Image)
          {
              case "Green":
                  Image_BlackDim.Visible = true;
                  Image_RedDim.Visible = true;
                  Image_GreenDim.Visible = false;
                  break;
              case "Red":
                  Image_BlackDataKeyDim.Visible = true;
                  Image_RedDataKeyDim.Visible = false;
                  Image_GreenDataKeyDim.Visible = true;
                  break;
              case "Black":
                  Image_BlackDim.Visible = false;
                  Image_RedDim.Visible = true;
                  Image_GreenDim.Visible = true;
                  break;
              case "None":
              default:
                  Image_BlackDim.Visible = true;
                  Image_RedDim.Visible = true;
                  Image_GreenDim.Visible = true;
                  break;
          }
      }
  </code></pre>
  
  <p>Naturally all my indicators are also put in place when I construct the form, so they can't be static either.  So having <code>DeviceCheck</code> return the string message to be displayed works, but I can't really have it ALSO return the string that <code>SetImages()</code> uses. </p>
  
  <p>Well... I could, by returning a struct with multiple strings, but is there a better way?</p>
  
  <p><strong>EDIT:</strong> Here's my working solution, based on Eric's advice:</p>
  
  <p>I start out with a struct for the status elements:</p>
  
  <pre><code>public struct Dev_status
      {
          public string Indicator1;
          public string Indicator2;
          public DK_status(string indicator1, string indicator1)
          {
              this.Indicator1 = indicator1;
              this.Indicator2 = indicator2;
          }
      }
  
      public static Dev_status status = new Dev_status(Device.Messages.thing1_offline,Device.Messages.thing2_offline);
  </code></pre>
  
  <p>The indicators now grab the messages from <code>status</code>:</p>
  
  <pre><code>    public void SetStatusBoxes()
      {
          Textbox_thing1_Status.Text = status.Indicator1;
          Textbox_thing2_Status.Text = status.Indicator2;
      }
  
      public void SetImages()
      {
          string IndicatorColor = "None";
          if (status.Indicator2 == Device.Messages.GreenThing) IndicatorColor = "Green";
          else if (status.Indicator2 == Device.Messages.RedThing) IndicatorColor = "Red";
          else if (status.Indicator2 == Device.Messages.BlackThing) IndicatorColor = "Black";
  
          switch(IndicatorColor)
          {
              case "Green":
                  Image_BlackDim.Visible = true;
                  Image_RedDim.Visible = true;
                  Image_GreenDim.Visible = false;
                  break;
              case "Red":
                  Image_BlackDim.Visible = true;
                  Image_RedDim.Visible = false;
                  Image_GreenDim.Visible = true;
                  break;
              case "Black":
                  Image_BlackDim.Visible = false;
                  Image_RedDim.Visible = true;
                  Image_GreenDim.Visible = true;
                  break;
              case "None":
              default:
                  Image_BlackDim.Visible = true;
                  Image_RedDim.Visible = true;
                  Image_GreenDim.Visible = true;
                  break;
          }
      }
  </code></pre>
  
  <p>And the timer just calls the <code>DeviceCheck</code> method and sets the indicators:</p>
  
  <pre><code>    private void timer1_Tick(object sender, EventArgs e)
      {
          status = Device.DeviceCheck();
          SetStatusBoxes();
          SetImages();
      }
  </code></pre>
  
  <p>Finally, <code>DeviceCheck</code> sets values for the status struct which is public, static, and inherited by the <code>Device</code> class:</p>
  
  <pre><code>    public static void DeviceCheck()
      {
          //Code that checks the device status
          status.Indicator1 = CheckDeviceConnected();
          status.Indicator2 = CheckDeviceType();
      }
  </code></pre>
  
  <p>This works pretty seamlessly.  In the end I didn't need to return values from <code>DeviceCheck</code> after all.  I'll still mark that idea as accepted though, since it led me in the right direction.</p>