libplctag.NET
libplctag.NET copied to clipboard
Example for NotifyPropertyChanged
Two common use-cases for this library are:
- Displaying the value of a Tag on a User Interface.
- Keeping a recording the changes to a Tag value over time.
Both of these require monitoring of the tag value, and notification when it changes. Implementing INotifyPropertyChanged is the canonical way of doing this for many .NET UI frameworks. Provide an example that shows how to do this.
I think its going to look something like this in the end, where it extends Tag<M,T>
by adding a ValueChanged event.
class NotifyValueChangedTag<M,T> : Tag<M,T>
where M : IPlcMapper<T>, new()
{
public event EventHandler<EventArgs> ValueChanged;
private int previousHash;
public NotifyValueChangedTag()
{
ReadCompleted += NotifyValueChangedTag_ReadCompleted;
}
private void NotifyValueChangedTag_ReadCompleted(object sender, TagEventArgs e)
{
var currentHash = this.Value.GetHashCode();
if (currentHash != previousHash)
{
ValueChanged?.Invoke(this, EventArgs.Empty);
}
previousHash = currentHash;
}
}
It requires that the type T
has a GetHashCode
method that is good at detecting changes. For atomic types, the builtin one should be okay, but for Udts they will need to override it.
class MyUdt
{
public int MyDint { get; set; }
public float MyFloat { get; set; }
public override int GetHashCode()
{
// Use the tuple shortcut to get an okay hash
return (MyDint,MyFloat).GetHashCode();
}
}
class MyUdtMapper : PlcMapperBase<MyUdt>
{
public override int? ElementSize => 8;
public override MyUdt Decode(Tag tag, int offset)
{
return new MyUdt()
{
MyDint = tag.GetInt32(offset),
MyFloat = tag.GetFloat32(offset + 4)
};
}
public override void Encode(Tag tag, int offset, MyUdt value)
{
tag.SetInt32(offset, value.MyDint);
tag.SetFloat32(offset + 4, value.MyFloat);
}
}
and should be able to used like this:
var myTag = new NotifyValueChangedTag<DintPlcMapper, int>()
{
Name = "MyTag",
Gateway = "127.0.0.1",
Path = "1,0",
PlcType = PlcType.ControlLogix,
Protocol = Protocol.ab_eip,
AutoSyncReadInterval = TimeSpan.FromMilliseconds(500)
};
myTag.ValueChanged += (s, e) => Console.WriteLine($"{myTag.Name} changed at {DateTime.Now} to {myTag.Value}");
var myUdtTag = new NotifyValueChangedTag<MyUdtMapper, MyUdt>()
{
Name = "MyUdtTag",
Gateway = "127.0.0.1",
Path = "1,0",
PlcType = PlcType.ControlLogix,
Protocol = Protocol.ab_eip,
AutoSyncReadInterval = TimeSpan.FromMilliseconds(500)
};
myUdtTag.ValueChanged += (s, e) => Console.WriteLine($"{myUdtTag.Name} changed at {DateTime.Now} to {myUdtTag.Value.MyDint}|{myUdtTag.Value.MyFloat}");
ExampleNotifyChanged
has been added to the examples list.