Peter Hansen
Peter Hansen

Reputation: 81

Update UI from dynamic created class

I am dynamic creating several classes and labels. I want to update the label text from my class, but I don't have any idea how to implement it.

My class:

  public partial class ScannerUtility : INotifyPropertyChanged
{
    public System.Timers.Timer timerHeartBeat = new System.Timers.Timer();
    public DateTime lastHeartBeat = new DateTime();
    public string heartBeatMessage = string.Empty;
    public event PropertyChangedEventHandler PropertyChanged;


    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    public void EnableScannerUtility()
    {
        timerHeartBeat = new System.Timers.Timer();
        timerHeartBeat.AutoReset = true;
        timerHeartBeat.Interval = 5000;// 35000;
        timerHeartBeat.Elapsed += TimerHeartBeat_Elapsed;
        timerHeartBeat.Start();
    }

    private void TimerHeartBeat_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        TimeSpan timeSinceLastHeartbeat = DateTime.Now.ToUniversalTime() - lastHeartBeat;
        if (timeSinceLastHeartbeat > TimeSpan.FromSeconds(30))
        {
            HeartBeatMessage = "No Answer from Scanner";
        }
        else
        {
            HeartBeatMessage = "Scanner OK";
        }
    }

    public string HeartBeatMessage
    {
        get { return this.heartBeatMessage; }

        set
        {
            if (value != this.heartBeatMessage)
            {
                this.heartBeatMessage = value;
                NotifyPropertyChanged("heartBeatMessage");
            }
        }
    }


}

And the loop where I created it from the main form:

 private void CreateSckanners()
    {
       foreach (BarCodeNodes item in iBarcodeScanners)
        {
            ScannerUtility util = new ScannerUtility();
            util.EnableScannerUtility();

            Label lbl = new Label();
            lbl.Text = item.IP.ToString();
            lbl.Name = item.IP.ToString();
            lbl.DataBindings.Add("Text", util, "HeartBeatMessage", false, DataSourceUpdateMode.OnPropertyChanged);
            flowLayoutPanel1.Controls.Add(lbl);
            flowLayoutPanel1.Update();
        }
    }

I want the Label to be updated when the timer is elapsed.

Upvotes: 0

Views: 106

Answers (2)

jlvaquero
jlvaquero

Reputation: 8785

bokibeg is right. I put the code in case someone is interested.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace WindowsFormsApplication1
{
 public partial class Form1 : Form
 {
  public Form1()
  {
   InitializeComponent();
   this.Load += new EventHandler(Form1_Load);
  }

  void Form1_Load(object sender, EventArgs e)
  {
   ScannerUtility util = new ScannerUtility(SynchronizationContext.Current);
   util.EnableScannerUtility();
   util.HeartBeatMessage = "Waiting for scanner...";

   this.SuspendLayout();
   Label lbl = new Label();
   lbl.Text = "Waiting for scanner...";
   lbl.Name = "lblTimer";
   lbl.Location = new System.Drawing.Point(15, 15);
   lbl.AutoSize = true;
   lbl.DataBindings.Add("Text", util, "HeartBeatMessage", false, DataSourceUpdateMode.OnPropertyChanged);
   this.Controls.Add(lbl);
   this.ResumeLayout(true);
  }
 }

 public partial class ScannerUtility : INotifyPropertyChanged
 {
  private SynchronizationContext _uiThreadContext;
  public System.Timers.Timer timerHeartBeat = new System.Timers.Timer();
  public DateTime lastHeartBeat = new DateTime();
  public string heartBeatMessage = string.Empty;
  public event PropertyChangedEventHandler PropertyChanged;

  public ScannerUtility(SynchronizationContext uiThreadContext)
  {
   _uiThreadContext = uiThreadContext;
  }

  private void NotifyPropertyChanged(String info)
  {
   if (PropertyChanged != null)
   {
    _uiThreadContext.Post(onUIPropertyChanged, new PropertyChangedEventArgs(info));
   }
   ;
  }

  private void onUIPropertyChanged(object state)
  {
    PropertyChanged(this, (PropertyChangedEventArgs)state);
  }

  public void EnableScannerUtility()
  {
   timerHeartBeat = new System.Timers.Timer();
   timerHeartBeat.AutoReset = true;
   timerHeartBeat.Interval = 5000;// 35000;
   timerHeartBeat.Elapsed += TimerHeartBeat_Elapsed;
   timerHeartBeat.Start();
  }

  private void TimerHeartBeat_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
  {
   TimeSpan timeSinceLastHeartbeat = DateTime.Now.ToUniversalTime() - lastHeartBeat;
   if (timeSinceLastHeartbeat > TimeSpan.FromSeconds(30))
   {
    HeartBeatMessage = "No Answer from Scanner";
   }
   else
   {
    HeartBeatMessage = "Scanner OK";
   }
  }

  public string HeartBeatMessage
  {
   get
   {
    return this.heartBeatMessage;
   }

   set
   {
    if (value != this.heartBeatMessage)
    {
     this.heartBeatMessage = value;
     NotifyPropertyChanged("HeartBeatMessage");
    }
   }
  }
 }
}

Upvotes: 0

jlvaquero
jlvaquero

Reputation: 8785

I'm affraid that you can not use DataBindigns in your situation. You have to stick whith the InvokeRequired style. Here, SO question about updating controls in another thread.

Upvotes: 1

Related Questions