Chapter 8 综合练习2
本文示例源码地址是: StdUnit.Tags.WPFDemo ,位于分支 eg-2 中
你可以直接使用StdUnit.Tags.Templates 模板,执行命令
dotnet new tags.wpf来创建一个脚手架,并基于它来微调成这里代码。
在上一篇,我们讲述了外部意图的适用场景和工作机制。在这里,我们打算在综合练习一的基础上,演示如何使用意图在Logicet外部变更点位。
作为示例,我们将演示如何通过按钮在Logicet外部变更点位。之前我们都是基于dotnet/reactive进行演示,这次我们尝试使用Cysharp/R3来完成这个任务。
首先移除之前的StdUnit.Tags.RxExtensions依赖,改用StdUnit.Tags.R3Extensions:
<PackageReference Include="StdUnit.Tags.R3Extensions" Version="1.0.0" />
<PackageReference Include="R3Extensions.WPF" Version="1.3.1" />
这里的R3Extensions.WPF是R3官方为WPF平台开发的扩展包。
界面调整
我们把之前的示例改成左右两栏,左侧放心跳状态的监视页面,右侧放一个切换心跳请求的按钮:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0">心跳请求</Label>
<TextBlock Name="txtReq" Grid.Row="0" Grid.Column="1" />
<Label Grid.Row="1" Grid.Column="0">心跳响应</Label>
<TextBlock Name="txtAck" Grid.Row="1" Grid.Column="1" />
</Grid>
<Grid Grid.Column="1">
<Button x:Name="btnToggle" Click="btnToggle_Click">切换心跳</Button>
</Grid>
</Grid>
这里单击事件btnToggle_Click是:
private async void btnToggle_Click(object sender, RoutedEventArgs e)
{
var proj = this._ctrl?.Project;
if(proj is null)
{
return;
}
var enqueue = proj.WriteIntent(
entry:"IoBox",
intent: (grp, ct) => {
var tag = proj.Tags.SelectTag("IoBox/通用状态/PLC/心跳请求");
var old = tag.GetTagValue<bool>();
tag.Value = !old;
return ValueTask.CompletedTask;
},
out var task
);
await task;
}
在这里,我们通过proj.WriteIntent(entry, intent, out task)进行了外部意图的写入。
信号监听
为了让左侧的信号界面能如实反映当前的信号状态,我们还需要几行监视代码:
req.Watch()
.ObserveOnCurrentDispatcher()
.Subscribe(evt =>
{
var newvalue = evt.NewValue;
this.txtReq.Text = newvalue?.ToString();
this.txtReq.Foreground= newvalue is true ? Brushes.Green : Brushes.Black;
})
.AddTo(_disposables);
ack.Watch()
.ObserveOnCurrentDispatcher()
.Subscribe(evt =>
{
var newvalue = evt.NewValue;
this.txtAck.Text = newvalue?.ToString();
this.txtAck.Foreground = newvalue is true ? Brushes.Green : Brushes.Black;
})
.AddTo(_disposables);
至此,一个简单的信号监控程序完成了: