WPF 适配器
通过 Dispatcher 把通道事件切到界面线程,并提供 TextBlock 绑定和可绑定源。
var attachment = this.AttachZeus(builder => builder.AddVirtualChannel("meter"));
var meter = attachment.Host.Channels.Get("meter");
meter.BindTo(EchoText);
DataContext = meter.AsBindingSource(this);
<TextBlock Text="{Binding LastText}" />
<TextBlock Text="{Binding StateText}" />
程序集:Zeus.Presentation.Wpf(目标框架 net8.0-windows)。
API
| API | 作用 |
|---|---|
Window.AttachZeus(...) | Loaded 时启动,Closed 时释放 |
BindTo / BindText | 写入 TextBlock.Text |
BindState | 显示通道状态 |
AsBindingSource(element) | 用该元素的 Dispatcher 发布属性变更 |
points.BindTo("temperature", textBlock) | 把点表值写到文本块 |
ChannelBindingSource 的属性:Name、State、StateText、LastText、LastHex、ReceivedCount。
接入已有 WPF / Prism 项目
如果你的 WPF 项目已经使用 Prism、DryIoc、Unity 或自己的业务容器,不需要让 Zeus 接管整个应用。推荐做法是:应用容器继续管理窗口、导航和 ViewModel,Zeus 作为一个单例服务注册进去,Zeus 自己负责通道、设备、采集循环和释放。
下面只展示 App.xaml.cs 里和 Zeus 有关的部分:
using Prism.Ioc;
using System.Windows;
using Zeus;
public partial class App : PrismApplication
{
private IZeusHost? _zeus;
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
var zeus = ZeusHost.Create(builder =>
{
builder.AddSerialPort("meter", "COM3", 9600);
builder.AddAcquisition(TimeSpan.FromMilliseconds(500));
});
_zeus = zeus;
containerRegistry.RegisterInstance<IZeusHost>(zeus);
containerRegistry.RegisterInstance<IChannelRegistry>(zeus.Channels);
containerRegistry.RegisterInstance<IPointTable>(zeus.Points);
}
protected override async void OnInitialized()
{
base.OnInitialized();
if (_zeus is not null)
{
await _zeus.StartAsync();
}
}
protected override void OnExit(ExitEventArgs e)
{
_zeus?.DisposeAsync().AsTask().GetAwaiter().GetResult();
base.OnExit(e);
}
}
ViewModel 中优先依赖更窄的接口,而不是到处解析整个宿主:
public sealed class MeterViewModel
{
private readonly IChannel _meter;
public MeterViewModel(IChannelRegistry channels)
{
_meter = channels.Get("meter");
}
public Task SendAsync(byte[] payload) => _meter.WriteAsync(payload);
}
需要显示采集点时,再把 IPointTable 注入到 ViewModel。
如果你的业务服务需要被 Zeus 的注册回调使用,可以把它注册到 Zeus 自己的 builder.Services 中:
_zeus = ZeusHost.Create(builder =>
{
builder.Services.AddSingleton<AlarmService>();
builder.AddSerialPort("meter", "COM3", 9600);
});
这种情况下要注意边界:Prism 容器和 Zeus 的 builder.Services 是两个容器。默认推荐把 Zeus 注册进 Prism 容器,供界面和 ViewModel 使用;不要强行让两个容器互相解析,除非你明确知道生命周期和释放顺序。
常见问题
- 绑定没有更新:属性名区分大小写,请对照上表。
- 在后台线程创建
AsBindingSource:必须传入窗口或控件,才能拿到正确的Dispatcher。 - 已有 Prism 容器怎么接:把
IZeusHost、IChannelRegistry或IPointTable注册成 Prism 单例,在应用启动时启动 Zeus,在退出时释放。 - 窗口正在关闭:此时的更新会被丢弃。