进程管理ui优化
This commit is contained in:
parent
9264596831
commit
ace97f14a6
@ -51,6 +51,7 @@ namespace BOB
|
||||
containerRegistry.RegisterForNavigation<MainView>("MainView");
|
||||
containerRegistry.RegisterForNavigation<MonitorView>("MonitorView");
|
||||
containerRegistry.RegisterForNavigation<Views.DataView>("DataView");
|
||||
containerRegistry.RegisterForNavigation<UpdateInfoView>("UpdateInfoView");
|
||||
//注册弹窗
|
||||
containerRegistry.RegisterDialog<MessageBoxView, MessageBoxViewModel>("MessageBox");
|
||||
containerRegistry.RegisterDialog<ParameterSetting, ParameterSettingViewModel>("ParameterSetting");
|
||||
|
||||
46
BOB/Services/BackfeedPollingRead.cs
Normal file
46
BOB/Services/BackfeedPollingRead.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using System;
|
||||
using System.CodeDom;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Services
|
||||
{
|
||||
public class BackfeedPollingRead : PollingRead
|
||||
{
|
||||
private Backfeed _Backfeed { get;set; }
|
||||
private IEventAggregator _eventAggregator { get;set; }
|
||||
public BackfeedPollingRead(IContainerProvider containerProvider) : base(containerProvider)
|
||||
{
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
var _devices = containerProvider.Resolve<Devices>();
|
||||
DeviceName = "Backfeed";
|
||||
_Backfeed = _devices.DeviceDic["Backfeed"]as Backfeed;
|
||||
}
|
||||
public double 实时电流 { get; set; } = double.NaN;
|
||||
public double 实时电压 { get; set; } = double.NaN;
|
||||
public double 实时功率 { get; set; } = double.NaN;
|
||||
|
||||
public override async Task ReadDeviceDataAsync(CancellationToken ct = default)
|
||||
{
|
||||
实时电流 = Random.Shared.NextDouble() * 10;
|
||||
实时电压 = Random.Shared.NextDouble() * 10;
|
||||
实时功率 = Random.Shared.NextDouble() * 10;
|
||||
//实时电流 =await _Backfeed!.查询实时电流(ct);
|
||||
//实时电压 = await _Backfeed!.查询实时电压(ct);
|
||||
//实时功率 = await _Backfeed!.查询实时功率(ct);
|
||||
var datalist = new List<double>() { 实时电流, 实时电压, 实时功率 };
|
||||
var dataDic = new Dictionary<string, double>
|
||||
{
|
||||
{ "实时电流", 实时电流 },
|
||||
{ "实时电压", 实时电压 },
|
||||
{ "实时功率", 实时功率 }
|
||||
};
|
||||
_eventAggregator.GetEvent<CurveDataEvent>().Publish(("Backfeed", dataDic));
|
||||
}
|
||||
}
|
||||
}
|
||||
43
BOB/Services/EAEL9080PollingRead.cs
Normal file
43
BOB/Services/EAEL9080PollingRead.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Services
|
||||
{
|
||||
public class EAEL9080PollingRead:PollingRead
|
||||
{
|
||||
private EAEL9080 _EAEL9080 { get; set; }
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
public EAEL9080PollingRead(IContainerProvider containerProvider) : base(containerProvider)
|
||||
{
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
var _devices = containerProvider.Resolve<Devices>();
|
||||
DeviceName = "EAEL9080";
|
||||
_EAEL9080 = _devices.DeviceDic["EAEL9080"] as EAEL9080;
|
||||
}
|
||||
public double 实时电流 { get; set; } = double.NaN;
|
||||
public double 实时电压 { get; set; } = double.NaN;
|
||||
public double 实时功率 { get; set; } = double.NaN;
|
||||
public override async Task ReadDeviceDataAsync(CancellationToken ct = default)
|
||||
{
|
||||
实时电流 = Random.Shared.NextDouble() * 10;
|
||||
实时电压 = Random.Shared.NextDouble() * 10;
|
||||
实时功率 = Random.Shared.NextDouble() * 10;
|
||||
//实时电流 = await _EAEL9080!.查询电流(ct);
|
||||
//实时电压 = await _EAEL9080!.查询电压(ct);
|
||||
//实时功率 = await _EAEL9080!.查询功率(ct);
|
||||
var dataDic = new Dictionary<string, double>
|
||||
{
|
||||
{ "实时电流", 实时电流 },
|
||||
{ "实时电压", 实时电压 },
|
||||
{ "实时功率", 实时功率 }
|
||||
};
|
||||
_eventAggregator.GetEvent<CurveDataEvent>().Publish(("EAEL9080", dataDic));
|
||||
}
|
||||
}
|
||||
}
|
||||
43
BOB/Services/IT6724CPollingRead.cs
Normal file
43
BOB/Services/IT6724CPollingRead.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Services
|
||||
{
|
||||
public class IT6724CPollingRead : PollingRead
|
||||
{
|
||||
private IT6724C _IT6724C { get; set; }
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
public IT6724CPollingRead(IContainerProvider containerProvider) : base(containerProvider)
|
||||
{
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
var _devices = containerProvider.Resolve<Devices>();
|
||||
DeviceName = "Backfeed";
|
||||
_IT6724C = _devices.DeviceDic["IT6724C"] as IT6724C;
|
||||
}
|
||||
public double 实时电流 { get; set; } = double.NaN;
|
||||
public double 实时电压 { get; set; } = double.NaN;
|
||||
public double 实时功率 { get; set; } = double.NaN;
|
||||
public override async Task ReadDeviceDataAsync(CancellationToken ct = default)
|
||||
{
|
||||
实时电流 = Random.Shared.NextDouble() * 10;
|
||||
实时电压 = Random.Shared.NextDouble() * 10;
|
||||
实时功率 = Random.Shared.NextDouble() * 10;
|
||||
//实时电流 = await _IT6724C!.查询实时电流(ct);
|
||||
//实时电压 = await _IT6724C!.查询实时电压(ct);
|
||||
//实时功率 = await _IT6724C!.查询实时功率(ct);
|
||||
var dataDic = new Dictionary<string, double>
|
||||
{
|
||||
{ "实时电流", 实时电流 },
|
||||
{ "实时电压", 实时电压 },
|
||||
{ "实时功率", 实时功率 }
|
||||
};
|
||||
_eventAggregator.GetEvent<CurveDataEvent>().Publish(("IT6724C", dataDic));
|
||||
}
|
||||
}
|
||||
}
|
||||
41
BOB/Services/LQ7500-DPollingRead.cs
Normal file
41
BOB/Services/LQ7500-DPollingRead.cs
Normal file
@ -0,0 +1,41 @@
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Services
|
||||
{
|
||||
public class LQ7500_DPollingRead : PollingRead
|
||||
{
|
||||
private LQ7500_D _LQ7500_D { get; set; }
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
public LQ7500_DPollingRead(IContainerProvider containerProvider) : base(containerProvider)
|
||||
{
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
var _devices = containerProvider.Resolve<Devices>();
|
||||
DeviceName = "LQ7500_D";
|
||||
_LQ7500_D = _devices.DeviceDic["LQ7500_D"] as LQ7500_D;
|
||||
}
|
||||
public double 内部传感器温度 { get; set; } = double.NaN;
|
||||
public double 外部传感器温度 { get; set; } = double.NaN;
|
||||
public double 水流量 { get; set; } = double.NaN;
|
||||
|
||||
public override async Task ReadDeviceDataAsync(CancellationToken ct = default)
|
||||
{
|
||||
内部传感器温度 = await _LQ7500_D.读取内部传感器温度();
|
||||
外部传感器温度 = await _LQ7500_D.读取外部传感器温度();
|
||||
水流量 = await _LQ7500_D.读取流量();
|
||||
var dataDic = new Dictionary<string, double>
|
||||
{
|
||||
{ "内部传感器温度", 内部传感器温度 },
|
||||
{ "外部传感器温度", 外部传感器温度 },
|
||||
{ "水流量", 水流量 }
|
||||
};
|
||||
_eventAggregator.GetEvent<CurveDataEvent>().Publish(("LQ7500_D", dataDic));
|
||||
}
|
||||
}
|
||||
}
|
||||
46
BOB/Services/PSB11000PollingRead.cs
Normal file
46
BOB/Services/PSB11000PollingRead.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Services
|
||||
{
|
||||
public class PSB11000PollingRead : PollingRead
|
||||
{
|
||||
private PSB11000 _PSB11000 { get; set; }
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
public PSB11000PollingRead(IContainerProvider containerProvider) : base(containerProvider)
|
||||
{
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
var _devices = containerProvider.Resolve<Devices>();
|
||||
DeviceName = "PSB11000";
|
||||
_PSB11000 = _devices.DeviceDic["PSB11000"] as PSB11000;
|
||||
}
|
||||
public double 实时电流 { get; set; } = double.NaN;
|
||||
public double 实时电压 { get; set; } = double.NaN;
|
||||
public double 实时功率 { get; set; } = double.NaN;
|
||||
|
||||
public override async Task ReadDeviceDataAsync(CancellationToken ct = default)
|
||||
{
|
||||
|
||||
实时电流 = Random.Shared.NextDouble() * 10;
|
||||
实时电压 = Random.Shared.NextDouble() * 10;
|
||||
实时功率 = Random.Shared.NextDouble() * 10;
|
||||
//实时电流 = await _PSB11000!.查询电流(ct);
|
||||
//实时电压 = await _PSB11000!.查询电压(ct);
|
||||
//实时功率 = await _PSB11000!.查询功率(ct);
|
||||
var datalist = new List<double>() { 实时电流, 实时电压, 实时功率 };
|
||||
var dataDic = new Dictionary<string, double>
|
||||
{
|
||||
{ "实时电流", 实时电流 },
|
||||
{ "实时电压", 实时电压 },
|
||||
{ "实时功率", 实时功率 }
|
||||
};
|
||||
_eventAggregator.GetEvent<CurveDataEvent>().Publish(("PSB11000", dataDic));
|
||||
}
|
||||
}
|
||||
}
|
||||
75
BOB/Services/PollingRead.cs
Normal file
75
BOB/Services/PollingRead.cs
Normal file
@ -0,0 +1,75 @@
|
||||
using BOB.Converters;
|
||||
using Common.PubEvent;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Services
|
||||
{
|
||||
public abstract class PollingRead
|
||||
{
|
||||
private CancellationTokenSource _pollingCancellationTokenSource;
|
||||
private Task? _pollingTask;
|
||||
public int PollingInterval = 1000;
|
||||
public string DeviceName{get;set;}="";
|
||||
private bool IsConnect{ get; set; }=false;
|
||||
public PollingRead(IContainerProvider containerProvider)
|
||||
{
|
||||
var _eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
_eventAggregator.GetEvent<ConnectionChangeEvent>().Subscribe(PollingConnection);
|
||||
}
|
||||
|
||||
private void PollingConnection((string, bool) tuple)
|
||||
{
|
||||
var (device, isConnect) = tuple;
|
||||
//System.Diagnostics.Debug.WriteLine($"PollingRead收到连接状态变化事件:设备={device},状态={isConnect}");
|
||||
if (device== DeviceName)
|
||||
{
|
||||
IsConnect = isConnect;
|
||||
}
|
||||
}
|
||||
|
||||
public void StartPolling()
|
||||
{
|
||||
if (_pollingTask != null)
|
||||
return;
|
||||
|
||||
if (_pollingCancellationTokenSource == null || _pollingCancellationTokenSource.IsCancellationRequested)
|
||||
_pollingCancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
_pollingTask = Task.Run(() => PollingLoop(_pollingCancellationTokenSource.Token));
|
||||
}
|
||||
|
||||
public void StopPolling()
|
||||
{
|
||||
_pollingCancellationTokenSource?.Cancel();
|
||||
_pollingTask = null;
|
||||
}
|
||||
|
||||
private async Task PollingLoop(CancellationToken ct)
|
||||
{
|
||||
while (!ct.IsCancellationRequested)
|
||||
{
|
||||
if (IsConnect)
|
||||
{
|
||||
await Task.Delay(PollingInterval, ct);
|
||||
|
||||
try
|
||||
{
|
||||
await ReadDeviceDataAsync(ct);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"轮询过程中发生错误: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public abstract Task ReadDeviceDataAsync(CancellationToken ct = default);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
32
BOB/Services/SQ0030G1DPollingRead.cs
Normal file
32
BOB/Services/SQ0030G1DPollingRead.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Services
|
||||
{
|
||||
public class SQ0030G1DPollingRead : PollingRead
|
||||
{
|
||||
private SQ0030G1D _SQ0030G1D { get; set; }
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
public SQ0030G1DPollingRead(IContainerProvider containerProvider) : base(containerProvider)
|
||||
{
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
var _devices = containerProvider.Resolve<Devices>();
|
||||
DeviceName = "SQ0030G1D";
|
||||
_SQ0030G1D = _devices.DeviceDic["SQ0030G1D"] as SQ0030G1D;
|
||||
}
|
||||
|
||||
|
||||
public override async Task ReadDeviceDataAsync(CancellationToken ct = default)
|
||||
{
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
30
BOB/Services/WS-68030-380TPollingRead.cs
Normal file
30
BOB/Services/WS-68030-380TPollingRead.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Services
|
||||
{
|
||||
public class WS_68030_380TPollingRead : PollingRead
|
||||
{
|
||||
private WS_68030_380T _WS_68030_380T { get; set; }
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
public WS_68030_380TPollingRead(IContainerProvider containerProvider) : base(containerProvider)
|
||||
{
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
var _devices = containerProvider.Resolve<Devices>();
|
||||
DeviceName = "WS_68030_380T";
|
||||
_WS_68030_380T = _devices.DeviceDic["WS_68030_380T"] as WS_68030_380T;
|
||||
}
|
||||
|
||||
public override async Task ReadDeviceDataAsync(CancellationToken ct = default)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
32
BOB/Services/ZXKSPollingRead.cs
Normal file
32
BOB/Services/ZXKSPollingRead.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Services
|
||||
{
|
||||
public class ZXKSPollingRead : PollingRead
|
||||
{
|
||||
private ZXKS _ZXKS { get; set; }
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
public ZXKSPollingRead(IContainerProvider containerProvider) : base(containerProvider)
|
||||
{
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
var _devices = containerProvider.Resolve<Devices>();
|
||||
DeviceName = "ZXKS";
|
||||
_ZXKS = _devices.DeviceDic["ZXKS"] as ZXKS;
|
||||
}
|
||||
public double 实时电流 { get; set; } = double.NaN;
|
||||
public double 实时电压 { get; set; } = double.NaN;
|
||||
public double 实时功率 { get; set; } = double.NaN;
|
||||
|
||||
public override async Task ReadDeviceDataAsync(CancellationToken ct = default)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
using Castle.DynamicProxy;
|
||||
using BOB.Services;
|
||||
using Castle.DynamicProxy;
|
||||
using DeviceCommand.Base;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
@ -13,10 +14,16 @@ namespace BOB.Singleton
|
||||
{
|
||||
public class Devices
|
||||
{
|
||||
public Devices(IContainerProvider containerProvider)
|
||||
{
|
||||
_containerProvider=containerProvider;
|
||||
}
|
||||
private IContainerProvider _containerProvider;
|
||||
private CancellationTokenSource _appCancellationTokenSource = new();
|
||||
public CancellationToken AppCancellationToken => _appCancellationTokenSource.Token;
|
||||
|
||||
public Dictionary<string, object> DeviceDic { get; private set; } = new Dictionary<string, object>();
|
||||
public Dictionary<string, PollingRead> PollingReadDic { get; private set; } = new Dictionary<string, PollingRead>();
|
||||
|
||||
private readonly ProxyGenerator _proxyGen = new ProxyGenerator();
|
||||
private readonly IInterceptor _loggingInterceptor = new LoggingInterceptor();
|
||||
@ -31,15 +38,11 @@ namespace BOB.Singleton
|
||||
private IModbusDevice ZXKSTDevice { get; set; }
|
||||
private Backfeed BackfeedDevice { get; set; }
|
||||
|
||||
public Devices()
|
||||
{
|
||||
}
|
||||
public void Init(List<DeviceConfigModel> deviceList)
|
||||
{
|
||||
foreach (var device in deviceList)
|
||||
{
|
||||
if (!device.IsEnabled) continue;
|
||||
|
||||
switch (device.DeviceType)
|
||||
{
|
||||
case "DeviceCommand.Device.E36233A":
|
||||
@ -235,6 +238,86 @@ namespace BOB.Singleton
|
||||
|
||||
}
|
||||
}
|
||||
public void StartPollingCollectionAsync()
|
||||
{
|
||||
foreach (var dc in DeviceDic)
|
||||
{
|
||||
var name = dc.Key;
|
||||
|
||||
switch (name)
|
||||
{
|
||||
case "Backfeed":
|
||||
{
|
||||
var polling = new BackfeedPollingRead(_containerProvider);
|
||||
PollingReadDic.Add("Backfeed", polling);
|
||||
polling.StartPolling();
|
||||
break;
|
||||
}
|
||||
|
||||
case "IT6724C":
|
||||
{
|
||||
var polling = new IT6724CPollingRead(_containerProvider);
|
||||
PollingReadDic.Add("IT6724C", polling);
|
||||
polling.StartPolling();
|
||||
break;
|
||||
}
|
||||
|
||||
case "LQ7500_D":
|
||||
{
|
||||
var polling = new LQ7500_DPollingRead(_containerProvider);
|
||||
PollingReadDic.Add("LQ7500_D", polling);
|
||||
polling.StartPolling();
|
||||
break;
|
||||
}
|
||||
|
||||
case "EAEL9080":
|
||||
{
|
||||
var polling = new EAEL9080PollingRead(_containerProvider);
|
||||
PollingReadDic.Add("EAEL9080", polling);
|
||||
polling.StartPolling();
|
||||
break;
|
||||
}
|
||||
|
||||
case "IOBoard":
|
||||
{
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "PSB11000":
|
||||
{
|
||||
var polling = new PSB11000PollingRead(_containerProvider);
|
||||
PollingReadDic.Add("PSB11000", polling);
|
||||
polling.StartPolling();
|
||||
break;
|
||||
}
|
||||
|
||||
case "WS_68030_380T":
|
||||
{
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "SQ0030G1D":
|
||||
{
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "ZXKS":
|
||||
{
|
||||
var polling = new ZXKSPollingRead(_containerProvider);
|
||||
PollingReadDic.Add("ZXKS", polling);
|
||||
polling.StartPolling();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
LoggerHelper.Warn($"未定义 {name} 的轮询处理器");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
using BOB.Models;
|
||||
using Logger;
|
||||
using Newtonsoft.Json;
|
||||
using Model;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
@ -42,6 +43,7 @@ namespace BOB
|
||||
public string SubProgramFilePath { get; set; } = @"D:\BOB\子程序\";
|
||||
|
||||
public string DefaultSubProgramFilePath { get; set; } = "";
|
||||
public ObservableCollection<string> CurSingleList { get; set; }
|
||||
public List<DeviceConfigModel> DeviceList { get; set; } = new();
|
||||
|
||||
#region 配置加载方法
|
||||
|
||||
@ -1,159 +0,0 @@
|
||||
using DeviceCommand.Base;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
|
||||
|
||||
namespace BOB.Tasks
|
||||
{
|
||||
public class HeartbeatManager<T> where T : class
|
||||
{
|
||||
private readonly T _device;
|
||||
private readonly CancellationTokenSource _cancellationTokenSource;
|
||||
private Task? _heartbeatTask;
|
||||
private const int HeartbeatInterval = 3000;
|
||||
bool IsActive = false;
|
||||
int ReConnectionAttempts = 0;
|
||||
private const int MaxReconnectAttempts = 10;
|
||||
|
||||
public HeartbeatManager(T device)
|
||||
{
|
||||
_device = device ?? throw new ArgumentNullException(nameof(device));
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
}
|
||||
|
||||
// 启动设备的心跳
|
||||
public void StartHeartbeat()
|
||||
{
|
||||
if (_heartbeatTask != null)
|
||||
return;
|
||||
|
||||
_heartbeatTask = Task.Run(() => HeartbeatLoop(_device, _cancellationTokenSource.Token));
|
||||
}
|
||||
|
||||
// 停止设备的心跳
|
||||
public void StopHeartbeat()
|
||||
{
|
||||
IsActive = false;
|
||||
_cancellationTokenSource.Cancel();
|
||||
_heartbeatTask?.Wait();
|
||||
_heartbeatTask = null;
|
||||
}
|
||||
|
||||
private async Task HeartbeatLoop(T device, CancellationToken ct)
|
||||
{
|
||||
while (!ct.IsCancellationRequested)
|
||||
{
|
||||
await Task.Delay(HeartbeatInterval, ct);
|
||||
|
||||
try
|
||||
{
|
||||
switch (device)
|
||||
{
|
||||
case EAEL9080 eAEL9080:
|
||||
await eAEL9080.SendAsync("SYSTem:REMote\r\n", ct);
|
||||
IsActive = true;
|
||||
break;
|
||||
|
||||
case IT6724C iT6724C:
|
||||
await iT6724C.SendAsync("SYSTem:REMote\r\n", ct);
|
||||
IsActive = true;
|
||||
break;
|
||||
|
||||
case PSB11000 pSB11000:
|
||||
await pSB11000.SendAsync("SYSTem:REMote\r\n", ct);
|
||||
IsActive = true;
|
||||
break;
|
||||
|
||||
case SQ0030G1D sQ0030G1D:
|
||||
await sQ0030G1D.SendAsync("SYSTem:REMote\r\n", ct);
|
||||
IsActive = true;
|
||||
break;
|
||||
|
||||
case WS_68030_380T wS_68030_380T:
|
||||
await wS_68030_380T.ReadCoilsAsync(1,0,1);
|
||||
IsActive = true;
|
||||
break;
|
||||
|
||||
case IOBoard iOBoard:
|
||||
await iOBoard.ReadCoilsAsync(1, 0, 1);
|
||||
IsActive = true;
|
||||
break;
|
||||
|
||||
case LQ7500_D lQ7500_D:
|
||||
await lQ7500_D.ReadCoilsAsync(1, 0, 1);
|
||||
IsActive = true;
|
||||
break;
|
||||
|
||||
case ZXKS zXKS:
|
||||
await zXKS.ReadCoilsAsync(1, 0, 1);
|
||||
IsActive = true;
|
||||
break;
|
||||
|
||||
case Backfeed backfeed:
|
||||
if (backfeed.CurrentInstance is E36233A e36233A)
|
||||
{
|
||||
await e36233A.SendAsync("SYSTem:REMote\r\n", ct);
|
||||
IsActive = true;
|
||||
}
|
||||
else if (backfeed.CurrentInstance is IT6724CReverse iT6724CReverse)
|
||||
{
|
||||
await iT6724CReverse.SendAsync("SYSTem:REMote\r\n", ct);
|
||||
IsActive = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
IsActive = false;
|
||||
ReConnectionAttempts++;
|
||||
if (MaxReconnectAttempts < ReConnectionAttempts)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"重连次数超过上限,停止重连:{device.GetType().Name}");
|
||||
StopHeartbeat();
|
||||
return;
|
||||
}
|
||||
await ReconnectDevice(device, ct);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ReconnectDevice(T device, CancellationToken ct)
|
||||
{
|
||||
try
|
||||
{
|
||||
bool result = false;
|
||||
if (device is ITcp itcpDevice)
|
||||
{
|
||||
result = await itcpDevice.ConnectAsync(CancellationToken.None);
|
||||
}
|
||||
else if (device is IModbusDevice imodbusDevice)
|
||||
{
|
||||
result = await imodbusDevice.ConnectAsync(CancellationToken.None);
|
||||
}
|
||||
else if (device is ISerialPort iserialPortDevice)
|
||||
{
|
||||
result = await iserialPortDevice.ConnectAsync(CancellationToken.None);
|
||||
}
|
||||
else if (device is Backfeed backfeedDevice)
|
||||
{
|
||||
if (backfeedDevice.CurrentInstance is ITcp itcpDevice1)
|
||||
{
|
||||
result = await itcpDevice1.ConnectAsync(CancellationToken.None);
|
||||
}
|
||||
else if (backfeedDevice.CurrentInstance is ISerialPort iserialPortDevice1)
|
||||
{
|
||||
result = await iserialPortDevice1.ConnectAsync(CancellationToken.None);
|
||||
}
|
||||
}
|
||||
if (result == false) { LoggerHelper.ErrorWithNotify($"重连失败:{device.GetType().Name}"); }
|
||||
else ReConnectionAttempts=0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"重连异常:{device.GetType().Name}"+ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,12 @@
|
||||
using BOB.Singleton;
|
||||
using BOB.ViewModels.UserControls;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
using OxyPlot;
|
||||
using OxyPlot.Axes;
|
||||
using OxyPlot.Legends;
|
||||
using OxyPlot.Series;
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using Prism.Mvvm;
|
||||
@ -62,7 +68,54 @@ namespace BOB.ViewModels.Dialogs
|
||||
get { return _OPP功率; }
|
||||
set { SetProperty(ref _OPP功率, value); }
|
||||
}
|
||||
private LineSeries _电压_lineSeries = new LineSeries { Title = "电压(V)", StrokeThickness = 2 };
|
||||
public LineSeries 电压_lineSeries
|
||||
{
|
||||
get => _电压_lineSeries;
|
||||
set => SetProperty(ref _电压_lineSeries, value);
|
||||
}
|
||||
|
||||
private LineSeries _电流_lineSeries = new LineSeries { Title = "电流(A)", StrokeThickness = 2 };
|
||||
public LineSeries 电流_lineSeries
|
||||
{
|
||||
get => _电流_lineSeries;
|
||||
set => SetProperty(ref _电流_lineSeries, value);
|
||||
}
|
||||
|
||||
private LineSeries _功率_lineSeries = new LineSeries { Title = "功率(W)", StrokeThickness = 2 };
|
||||
public LineSeries 功率_lineSeries
|
||||
{
|
||||
get => _功率_lineSeries;
|
||||
set => SetProperty(ref _功率_lineSeries, value);
|
||||
}
|
||||
private NumericalDisplayViewModel _电压MV = new NumericalDisplayViewModel();
|
||||
public NumericalDisplayViewModel 电压MV
|
||||
{
|
||||
get => _电压MV;
|
||||
set => SetProperty(ref _电压MV, value);
|
||||
}
|
||||
|
||||
private NumericalDisplayViewModel _电流MV = new NumericalDisplayViewModel();
|
||||
public NumericalDisplayViewModel 电流MV
|
||||
{
|
||||
get => _电流MV;
|
||||
set => SetProperty(ref _电流MV, value);
|
||||
}
|
||||
|
||||
private NumericalDisplayViewModel _功率MV = new NumericalDisplayViewModel();
|
||||
public NumericalDisplayViewModel 功率MV
|
||||
{
|
||||
get => _功率MV;
|
||||
set => SetProperty(ref _功率MV, value);
|
||||
}
|
||||
private PlotModel _曲线Model = new PlotModel();
|
||||
public PlotModel 曲线Model
|
||||
{
|
||||
get => _曲线Model;
|
||||
set => SetProperty(ref _曲线Model, value);
|
||||
}
|
||||
public DateTimeAxis TimeAxis { get; private set; }
|
||||
public LinearAxis ValueAxis { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region 命令
|
||||
@ -82,6 +135,7 @@ namespace BOB.ViewModels.Dialogs
|
||||
public ICommand DisableOPPCommand { get; private set; }
|
||||
public ICommand SetOPPCommand { get; private set; }
|
||||
public ICommand CloseCommand { get; private set; }
|
||||
public ICommand ResetViewCommand { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
@ -113,6 +167,55 @@ namespace BOB.ViewModels.Dialogs
|
||||
DisableOPPCommand = new AsyncDelegateCommand(OnDisableOPP);
|
||||
SetOPPCommand = new AsyncDelegateCommand(OnSetOPP);
|
||||
CloseCommand = new DelegateCommand(OnClose);
|
||||
ResetViewCommand = new DelegateCommand(ResetView);
|
||||
_eventAggregator.GetEvent<CurveDataEvent>().Subscribe(UpdateCurve);
|
||||
InitCurve();
|
||||
}
|
||||
private void ResetView()
|
||||
{
|
||||
曲线Model.ResetAllAxes();
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
private void InitCurve()
|
||||
{
|
||||
TimeAxis = new DateTimeAxis
|
||||
{
|
||||
Position = AxisPosition.Bottom,
|
||||
StringFormat = "HH:mm:ss",
|
||||
IntervalType = DateTimeIntervalType.Seconds,
|
||||
};
|
||||
ValueAxis = new LinearAxis
|
||||
{
|
||||
Position = AxisPosition.Left,
|
||||
};
|
||||
曲线Model.Axes.Add(TimeAxis);
|
||||
曲线Model.Axes.Add(ValueAxis);
|
||||
曲线Model.Series.Add(电压_lineSeries);
|
||||
曲线Model.Series.Add(电流_lineSeries);
|
||||
曲线Model.Series.Add(功率_lineSeries);
|
||||
曲线Model.Legends.Add(new Legend()
|
||||
{
|
||||
LegendPosition = LegendPosition.TopRight,
|
||||
LegendOrientation = LegendOrientation.Vertical,
|
||||
LegendPlacement = LegendPlacement.Inside
|
||||
});
|
||||
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
|
||||
private void UpdateCurve((string device, Dictionary<string, double> data )tuple)
|
||||
{
|
||||
var (device, data) = tuple;
|
||||
if (device != "IT6724C") return;
|
||||
电流MV.MonitorValue = data["实时电流"];
|
||||
电压MV.MonitorValue = data["实时电压"];
|
||||
功率MV.MonitorValue = data["实时功率"];
|
||||
|
||||
var now = DateTimeAxis.ToDouble(DateTime.Now);
|
||||
电流_lineSeries.Points.Add(new DataPoint(now, data["实时电流"]));
|
||||
电压_lineSeries.Points.Add(new DataPoint(now, data["实时电压"]));
|
||||
功率_lineSeries.Points.Add(new DataPoint(now, data["实时功率"]));
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,13 +1,19 @@
|
||||
using BOB.Singleton;
|
||||
using BOB.ViewModels.UserControls;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
using OxyPlot;
|
||||
using OxyPlot.Annotations;
|
||||
using OxyPlot.Axes;
|
||||
using OxyPlot.Legends;
|
||||
using OxyPlot.Series;
|
||||
using Prism.Commands;
|
||||
using Prism.Mvvm;
|
||||
using Prism.Events;
|
||||
using Prism.Mvvm;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
using BOB.ViewModels.UserControls;
|
||||
|
||||
namespace BOB.ViewModels.Dialogs
|
||||
{
|
||||
@ -17,12 +23,31 @@ namespace BOB.ViewModels.Dialogs
|
||||
private string _Title = "低压直流负载";
|
||||
private string _设备标识字符串;
|
||||
private string _负载模式;
|
||||
private string _电流LA;
|
||||
private string _电流LB;
|
||||
private LineSeries _电压_lineSeries = new LineSeries
|
||||
{
|
||||
Title = "电压(V)",
|
||||
StrokeThickness = 2,
|
||||
};
|
||||
private LineSeries _电流_lineSeries = new LineSeries
|
||||
{
|
||||
Title = "电流(A)",
|
||||
StrokeThickness = 2,
|
||||
};
|
||||
private LineSeries _功率_lineSeries = new LineSeries
|
||||
{
|
||||
Title = "功率(W)",
|
||||
StrokeThickness = 2,
|
||||
};
|
||||
private NumericalDisplayViewModel _电压MV=new();
|
||||
private NumericalDisplayViewModel _电流MV = new();
|
||||
private NumericalDisplayViewModel _功率MV=new();
|
||||
private PlotModel _曲线Model = new();
|
||||
|
||||
public PlotModel 曲线Model
|
||||
{
|
||||
get { return _曲线Model; }
|
||||
set { SetProperty(ref _曲线Model, value); }
|
||||
}
|
||||
public string Title
|
||||
{
|
||||
get { return _Title; }
|
||||
@ -41,16 +66,21 @@ namespace BOB.ViewModels.Dialogs
|
||||
set { SetProperty(ref _负载模式, value); }
|
||||
}
|
||||
|
||||
public string 电流LA
|
||||
public LineSeries 电流_lineSeries
|
||||
{
|
||||
get { return _电流LA; }
|
||||
set { SetProperty(ref _电流LA, value); }
|
||||
get { return _电流_lineSeries; }
|
||||
set { SetProperty(ref _电流_lineSeries, value); }
|
||||
}
|
||||
|
||||
public string 电流LB
|
||||
public LineSeries 电压_lineSeries
|
||||
{
|
||||
get { return _电流LB; }
|
||||
set { SetProperty(ref _电流LB, value); }
|
||||
get { return _电压_lineSeries; }
|
||||
set { SetProperty(ref _电压_lineSeries, value); }
|
||||
}
|
||||
public LineSeries 功率_lineSeries
|
||||
{
|
||||
get { return _功率_lineSeries; }
|
||||
set { SetProperty(ref _功率_lineSeries, value); }
|
||||
}
|
||||
public NumericalDisplayViewModel 电压MV
|
||||
{
|
||||
@ -67,6 +97,8 @@ namespace BOB.ViewModels.Dialogs
|
||||
get { return _功率MV; }
|
||||
set { SetProperty(ref _功率MV, value); }
|
||||
}
|
||||
public DateTimeAxis TimeAxis { get; private set; }
|
||||
public LinearAxis ValueAxis { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region 命令
|
||||
@ -78,6 +110,7 @@ namespace BOB.ViewModels.Dialogs
|
||||
public ICommand 电源输出关命令 { get; private set; }
|
||||
public ICommand 关闭命令 { get; private set; }
|
||||
public ICommand 查询设备信息命令 { get; private set; }
|
||||
public ICommand ResetViewCommand { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
@ -99,8 +132,56 @@ namespace BOB.ViewModels.Dialogs
|
||||
电源输出关命令 = new AsyncDelegateCommand(OnPowerOff);
|
||||
关闭命令 = new DelegateCommand(OnOff);
|
||||
查询设备信息命令 = new AsyncDelegateCommand(OnQueryDeviceInfo);
|
||||
ResetViewCommand = new DelegateCommand(ResetView);
|
||||
_eventAggregator.GetEvent<CurveDataEvent>().Subscribe(UpdateCurve);
|
||||
InitCurve();
|
||||
}
|
||||
private void ResetView()
|
||||
{
|
||||
曲线Model.ResetAllAxes();
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
private void InitCurve()
|
||||
{
|
||||
TimeAxis = new DateTimeAxis
|
||||
{
|
||||
Position = AxisPosition.Bottom,
|
||||
StringFormat = "HH:mm:ss",
|
||||
IntervalType = DateTimeIntervalType.Seconds,
|
||||
};
|
||||
ValueAxis = new LinearAxis
|
||||
{
|
||||
Position = AxisPosition.Left,
|
||||
};
|
||||
曲线Model.Axes.Add(TimeAxis);
|
||||
曲线Model.Axes.Add(ValueAxis);
|
||||
曲线Model.Series.Add(电压_lineSeries);
|
||||
曲线Model.Series.Add(电流_lineSeries);
|
||||
曲线Model.Series.Add(功率_lineSeries);
|
||||
曲线Model.Legends.Add(new Legend()
|
||||
{
|
||||
LegendPosition = LegendPosition.TopRight,
|
||||
LegendOrientation = LegendOrientation.Vertical,
|
||||
LegendPlacement = LegendPlacement.Inside
|
||||
});
|
||||
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
|
||||
private void UpdateCurve((string device, Dictionary<string,double> data) tuple)
|
||||
{
|
||||
var (device, data) = tuple;
|
||||
if (device != "EAEL9080") return;
|
||||
电流MV.MonitorValue = data["实时电流"];
|
||||
电压MV.MonitorValue = data["实时电压"];
|
||||
功率MV.MonitorValue = data["实时功率"];
|
||||
|
||||
var now = DateTimeAxis.ToDouble(DateTime.Now);
|
||||
电流_lineSeries.Points.Add(new DataPoint(now, data["实时电流"]));
|
||||
电压_lineSeries.Points.Add(new DataPoint(now, data["实时电压"]));
|
||||
功率_lineSeries.Points.Add(new DataPoint(now, data["实时功率"]));
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
private async Task OnQueryDeviceInfo()
|
||||
{
|
||||
设备标识字符串 = await device.查询设备信息();
|
||||
|
||||
@ -1,6 +1,13 @@
|
||||
using BOB.Singleton;
|
||||
using BOB.ViewModels.UserControls;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
using OxyPlot;
|
||||
using OxyPlot.Annotations;
|
||||
using OxyPlot.Axes;
|
||||
using OxyPlot.Legends;
|
||||
using OxyPlot.Series;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -12,52 +19,97 @@ namespace BOB.ViewModels.Dialogs
|
||||
{
|
||||
public class IT6724CViewModel : BindableBase, IDialogAware
|
||||
{
|
||||
|
||||
#region 属性
|
||||
|
||||
private string _title = "低压直流电源";
|
||||
public string Title
|
||||
{
|
||||
get { return _title; }
|
||||
set { SetProperty(ref _title, value); }
|
||||
get => _title;
|
||||
set => SetProperty(ref _title, value);
|
||||
}
|
||||
|
||||
private string _设备标识字符串;
|
||||
public string 设备标识字符串
|
||||
{
|
||||
get { return _设备标识字符串; }
|
||||
set { SetProperty(ref _设备标识字符串, value); }
|
||||
get => _设备标识字符串;
|
||||
set => SetProperty(ref _设备标识字符串, value);
|
||||
}
|
||||
|
||||
private string _输出电压;
|
||||
public string 输出电压
|
||||
{
|
||||
get { return _输出电压; }
|
||||
set { SetProperty(ref _输出电压, value); }
|
||||
get => _输出电压;
|
||||
set => SetProperty(ref _输出电压, value);
|
||||
}
|
||||
|
||||
private string _输出电流;
|
||||
public string 输出电流
|
||||
{
|
||||
get { return _输出电流; }
|
||||
set { SetProperty(ref _输出电流, value); }
|
||||
get => _输出电流;
|
||||
set => SetProperty(ref _输出电流, value);
|
||||
}
|
||||
|
||||
private string _OCP电流;
|
||||
public string OCP电流
|
||||
{
|
||||
get { return _OCP电流; }
|
||||
set { SetProperty(ref _OCP电流, value); }
|
||||
get => _OCP电流;
|
||||
set => SetProperty(ref _OCP电流, value);
|
||||
}
|
||||
|
||||
private string _OVP电压;
|
||||
public string OVP电压
|
||||
{
|
||||
get { return _OVP电压; }
|
||||
set { SetProperty(ref _OVP电压, value); }
|
||||
get => _OVP电压;
|
||||
set => SetProperty(ref _OVP电压, value);
|
||||
}
|
||||
|
||||
private LineSeries _电压_lineSeries = new LineSeries { Title = "电压(V)", StrokeThickness = 2 };
|
||||
public LineSeries 电压_lineSeries
|
||||
{
|
||||
get => _电压_lineSeries;
|
||||
set => SetProperty(ref _电压_lineSeries, value);
|
||||
}
|
||||
|
||||
private LineSeries _电流_lineSeries = new LineSeries { Title = "电流(A)", StrokeThickness = 2 };
|
||||
public LineSeries 电流_lineSeries
|
||||
{
|
||||
get => _电流_lineSeries;
|
||||
set => SetProperty(ref _电流_lineSeries, value);
|
||||
}
|
||||
|
||||
private LineSeries _功率_lineSeries = new LineSeries { Title = "功率(W)", StrokeThickness = 2 };
|
||||
public LineSeries 功率_lineSeries
|
||||
{
|
||||
get => _功率_lineSeries;
|
||||
set => SetProperty(ref _功率_lineSeries, value);
|
||||
}
|
||||
private NumericalDisplayViewModel _电压MV = new NumericalDisplayViewModel();
|
||||
public NumericalDisplayViewModel 电压MV
|
||||
{
|
||||
get => _电压MV;
|
||||
set => SetProperty(ref _电压MV, value);
|
||||
}
|
||||
|
||||
private NumericalDisplayViewModel _电流MV = new NumericalDisplayViewModel();
|
||||
public NumericalDisplayViewModel 电流MV
|
||||
{
|
||||
get => _电流MV;
|
||||
set => SetProperty(ref _电流MV, value);
|
||||
}
|
||||
|
||||
private NumericalDisplayViewModel _功率MV = new NumericalDisplayViewModel();
|
||||
public NumericalDisplayViewModel 功率MV
|
||||
{
|
||||
get => _功率MV;
|
||||
set => SetProperty(ref _功率MV, value);
|
||||
}
|
||||
private PlotModel _曲线Model = new PlotModel();
|
||||
public PlotModel 曲线Model
|
||||
{
|
||||
get => _曲线Model;
|
||||
set => SetProperty(ref _曲线Model, value);
|
||||
}
|
||||
public DateTimeAxis TimeAxis { get; private set; }
|
||||
public LinearAxis ValueAxis { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region 命令
|
||||
public ICommand ConnectCommand { get; private set; }
|
||||
public ICommand DisconnectCommand { get; private set; }
|
||||
@ -76,6 +128,7 @@ namespace BOB.ViewModels.Dialogs
|
||||
public ICommand ClearOVPAlarmCommand { get; private set; }
|
||||
public ICommand SetOVPCommand { get; private set; }
|
||||
public ICommand CloseCommand { get; private set; }
|
||||
public ICommand ResetViewCommand { get; private set; }
|
||||
|
||||
#endregion
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
@ -104,8 +157,56 @@ namespace BOB.ViewModels.Dialogs
|
||||
_devices = containerProvider.Resolve<Devices>();
|
||||
_globalVariables = containerProvider.Resolve<GlobalVariables>();
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
ResetViewCommand = new DelegateCommand(ResetView);
|
||||
_eventAggregator.GetEvent<CurveDataEvent>().Subscribe(UpdateCurve);
|
||||
InitCurve();
|
||||
}
|
||||
private void ResetView()
|
||||
{
|
||||
曲线Model.ResetAllAxes();
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
private void InitCurve()
|
||||
{
|
||||
TimeAxis = new DateTimeAxis
|
||||
{
|
||||
Position = AxisPosition.Bottom,
|
||||
StringFormat = "HH:mm:ss",
|
||||
IntervalType = DateTimeIntervalType.Seconds,
|
||||
};
|
||||
ValueAxis = new LinearAxis
|
||||
{
|
||||
Position = AxisPosition.Left,
|
||||
};
|
||||
曲线Model.Axes.Add(TimeAxis);
|
||||
曲线Model.Axes.Add(ValueAxis);
|
||||
曲线Model.Series.Add(电压_lineSeries);
|
||||
曲线Model.Series.Add(电流_lineSeries);
|
||||
曲线Model.Series.Add(功率_lineSeries);
|
||||
曲线Model.Legends.Add(new Legend()
|
||||
{
|
||||
LegendPosition = LegendPosition.TopRight,
|
||||
LegendOrientation = LegendOrientation.Vertical,
|
||||
LegendPlacement = LegendPlacement.Inside
|
||||
});
|
||||
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
|
||||
private void UpdateCurve((string device, Dictionary<string, double> data) tuple)
|
||||
{
|
||||
var (device, data) = tuple;
|
||||
if (device != "IT6724C") return;
|
||||
电流MV.MonitorValue = data["实时电流"];
|
||||
电压MV.MonitorValue = data["实时电压"];
|
||||
功率MV.MonitorValue = data["实时功率"];
|
||||
|
||||
var now = DateTimeAxis.ToDouble(DateTime.Now);
|
||||
电流_lineSeries.Points.Add(new DataPoint(now, data["实时电流"]));
|
||||
电压_lineSeries.Points.Add(new DataPoint(now, data["实时电压"]));
|
||||
功率_lineSeries.Points.Add(new DataPoint(now, data["实时功率"]));
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
#region 命令处理方法
|
||||
private void OnClose()
|
||||
{
|
||||
|
||||
@ -1,6 +1,12 @@
|
||||
using BOB.Singleton;
|
||||
using BOB.ViewModels.UserControls;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
using OxyPlot;
|
||||
using OxyPlot.Axes;
|
||||
using OxyPlot.Legends;
|
||||
using OxyPlot.Series;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -48,7 +54,54 @@ namespace BOB.ViewModels.Dialogs
|
||||
get { return _OCP电流; }
|
||||
set { SetProperty(ref _OCP电流, value); }
|
||||
}
|
||||
private LineSeries _电压_lineSeries = new LineSeries { Title = "电压(V)", StrokeThickness = 2 };
|
||||
public LineSeries 电压_lineSeries
|
||||
{
|
||||
get => _电压_lineSeries;
|
||||
set => SetProperty(ref _电压_lineSeries, value);
|
||||
}
|
||||
|
||||
private LineSeries _电流_lineSeries = new LineSeries { Title = "电流(A)", StrokeThickness = 2 };
|
||||
public LineSeries 电流_lineSeries
|
||||
{
|
||||
get => _电流_lineSeries;
|
||||
set => SetProperty(ref _电流_lineSeries, value);
|
||||
}
|
||||
|
||||
private LineSeries _功率_lineSeries = new LineSeries { Title = "功率(W)", StrokeThickness = 2 };
|
||||
public LineSeries 功率_lineSeries
|
||||
{
|
||||
get => _功率_lineSeries;
|
||||
set => SetProperty(ref _功率_lineSeries, value);
|
||||
}
|
||||
private NumericalDisplayViewModel _电压MV = new NumericalDisplayViewModel();
|
||||
public NumericalDisplayViewModel 电压MV
|
||||
{
|
||||
get => _电压MV;
|
||||
set => SetProperty(ref _电压MV, value);
|
||||
}
|
||||
|
||||
private NumericalDisplayViewModel _电流MV = new NumericalDisplayViewModel();
|
||||
public NumericalDisplayViewModel 电流MV
|
||||
{
|
||||
get => _电流MV;
|
||||
set => SetProperty(ref _电流MV, value);
|
||||
}
|
||||
|
||||
private NumericalDisplayViewModel _功率MV = new NumericalDisplayViewModel();
|
||||
public NumericalDisplayViewModel 功率MV
|
||||
{
|
||||
get => _功率MV;
|
||||
set => SetProperty(ref _功率MV, value);
|
||||
}
|
||||
private PlotModel _曲线Model = new PlotModel();
|
||||
public PlotModel 曲线Model
|
||||
{
|
||||
get => _曲线Model;
|
||||
set => SetProperty(ref _曲线Model, value);
|
||||
}
|
||||
public DateTimeAxis TimeAxis { get; private set; }
|
||||
public LinearAxis ValueAxis { get; private set; }
|
||||
|
||||
#endregion
|
||||
#region 命令
|
||||
@ -66,6 +119,7 @@ namespace BOB.ViewModels.Dialogs
|
||||
public ICommand SetCCCurrentCommand { get; private set; }
|
||||
public ICommand SetOCPCurrentCommand { get; private set; }
|
||||
public ICommand CloseCommand { get; private set; }
|
||||
public ICommand ResetViewCommand { get; private set; }
|
||||
|
||||
#endregion
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
@ -90,7 +144,55 @@ namespace BOB.ViewModels.Dialogs
|
||||
SetCCCurrentCommand = new AsyncDelegateCommand(OnSetCCCurrent);
|
||||
SetOCPCurrentCommand = new AsyncDelegateCommand(OnSetOCPCurrent);
|
||||
CloseCommand = new DelegateCommand(OnClose);
|
||||
ResetViewCommand = new DelegateCommand(ResetView);
|
||||
_eventAggregator.GetEvent<CurveDataEvent>().Subscribe(UpdateCurve);
|
||||
InitCurve();
|
||||
}
|
||||
private void ResetView()
|
||||
{
|
||||
曲线Model.ResetAllAxes();
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
private void InitCurve()
|
||||
{
|
||||
TimeAxis = new DateTimeAxis
|
||||
{
|
||||
Position = AxisPosition.Bottom,
|
||||
StringFormat = "HH:mm:ss",
|
||||
IntervalType = DateTimeIntervalType.Seconds,
|
||||
};
|
||||
ValueAxis = new LinearAxis
|
||||
{
|
||||
Position = AxisPosition.Left,
|
||||
};
|
||||
曲线Model.Axes.Add(TimeAxis);
|
||||
曲线Model.Axes.Add(ValueAxis);
|
||||
曲线Model.Series.Add(电压_lineSeries);
|
||||
曲线Model.Series.Add(电流_lineSeries);
|
||||
曲线Model.Series.Add(功率_lineSeries);
|
||||
曲线Model.Legends.Add(new Legend()
|
||||
{
|
||||
LegendPosition = LegendPosition.TopRight,
|
||||
LegendOrientation = LegendOrientation.Vertical,
|
||||
LegendPlacement = LegendPlacement.Inside
|
||||
});
|
||||
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
|
||||
private void UpdateCurve((string device, Dictionary<string, double> data) tuple)
|
||||
{
|
||||
var (device, data) = tuple;
|
||||
if (device != "IT6724C") return;
|
||||
电流MV.MonitorValue = data["实时电流"];
|
||||
电压MV.MonitorValue = data["实时电压"];
|
||||
功率MV.MonitorValue = data["实时功率"];
|
||||
|
||||
var now = DateTimeAxis.ToDouble(DateTime.Now);
|
||||
电流_lineSeries.Points.Add(new DataPoint(now, data["实时电流"]));
|
||||
电压_lineSeries.Points.Add(new DataPoint(now, data["实时电压"]));
|
||||
功率_lineSeries.Points.Add(new DataPoint(now, data["实时功率"]));
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
#region Command Handlers
|
||||
private void OnClose()
|
||||
|
||||
@ -44,6 +44,7 @@ namespace BOB.ViewModels
|
||||
{
|
||||
_devices.Init(SystemConfig.Instance.DeviceList);
|
||||
await _devices.ConnectAllDevicesAsync();
|
||||
_devices.StartPollingCollectionAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -51,7 +52,7 @@ namespace BOB.ViewModels
|
||||
}
|
||||
finally
|
||||
{
|
||||
_eventAggregator.GetEvent<WaitingEvent>().Publish(false);
|
||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(false);
|
||||
}
|
||||
}
|
||||
#region 导航
|
||||
@ -61,7 +62,7 @@ namespace BOB.ViewModels
|
||||
{
|
||||
if (!_isInitialized)
|
||||
{
|
||||
_eventAggregator.GetEvent<WaitingEvent>().Publish(true);
|
||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(true);
|
||||
_ = InitializeDevicesAsync();
|
||||
_isInitialized = true;
|
||||
}
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
using BOB.Singleton;
|
||||
using BOB.Services;
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using Common.PubEvents;
|
||||
using Logger;
|
||||
using Microsoft.Win32;
|
||||
using OxyPlot;
|
||||
using OxyPlot.Axes;
|
||||
using OxyPlot.Legends;
|
||||
using OxyPlot.Series;
|
||||
using Prism.Dialogs;
|
||||
@ -10,6 +13,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
@ -27,13 +31,6 @@ namespace BOB.ViewModels
|
||||
get => _CurveModel;
|
||||
set => SetProperty(ref _CurveModel, value);
|
||||
}
|
||||
private List<LineSeries> _signalSeries = new List<LineSeries>();
|
||||
|
||||
public List<LineSeries> SignalSeries
|
||||
{
|
||||
get => _signalSeries;
|
||||
set => SetProperty(ref _signalSeries, value);
|
||||
}
|
||||
private Dictionary<string, LineSeries> _SeriesDic = new ();
|
||||
|
||||
public Dictionary<string,LineSeries> SeriesDic
|
||||
@ -69,12 +66,19 @@ namespace BOB.ViewModels
|
||||
get => _SelectedSaveDays;
|
||||
set => SetProperty(ref _SelectedSaveDays, value);
|
||||
}
|
||||
private ObservableCollection<string> _CurSingleList=new();
|
||||
//private ObservableCollection<string> _CurSingleList=new();
|
||||
|
||||
public ObservableCollection<string> CurSingleList
|
||||
{
|
||||
get => _CurSingleList;
|
||||
set => SetProperty(ref _CurSingleList, value);
|
||||
get => SystemConfig.Instance.CurSingleList;
|
||||
set
|
||||
{
|
||||
if (SystemConfig.Instance.CurSingleList != value)
|
||||
{
|
||||
SystemConfig.Instance.CurSingleList = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
private ObservableCollection<string> _DeviceSingleList = new();
|
||||
|
||||
@ -83,8 +87,6 @@ namespace BOB.ViewModels
|
||||
get => _DeviceSingleList;
|
||||
set => SetProperty(ref _DeviceSingleList, value);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
#region 命令
|
||||
public ICommand ResetViewCommand { get; set; }
|
||||
@ -97,135 +99,113 @@ namespace BOB.ViewModels
|
||||
private IEventAggregator _eventAggregator;
|
||||
private IDialogService _dialogService;
|
||||
private static Random _random = new Random();
|
||||
private DispatcherTimer _refreshTimer;
|
||||
private Devices _devices { get; set; }
|
||||
private readonly IProgress<(string name, double value)> _progress;
|
||||
public MonitorViewModel(IEventAggregator eventAggregator, IDialogService dialogService, IContainerProvider containerProvider )
|
||||
{
|
||||
_dialogService = dialogService;
|
||||
_eventAggregator = eventAggregator;
|
||||
_devices = containerProvider.Resolve<Devices>();
|
||||
ResetViewCommand = new DelegateCommand(ResetView);
|
||||
AddSignalCommand = new DelegateCommand(AddSignal);
|
||||
AddSignalCommand = new DelegateCommand<string>(AddSignal);
|
||||
RemoveSignalCommand = new DelegateCommand(RemoveSignal);
|
||||
ChanegPathCommand = new DelegateCommand(ChanegPath);
|
||||
SaveCommand = new DelegateCommand(Save);
|
||||
_eventAggregator.GetEvent<CurveDataEvent>().Subscribe(OnCurveDataReceived);
|
||||
_progress = new Progress<(string name, double value)>(UpdateCurveOnUI);
|
||||
InitData();
|
||||
|
||||
// 初始化模拟量曲线
|
||||
InitializeSimulatedSignals();
|
||||
|
||||
// 设置定时器定时更新模拟数据
|
||||
_timer = new DispatcherTimer
|
||||
{
|
||||
Interval = TimeSpan.FromSeconds(0.5) // 每1秒更新一次
|
||||
};
|
||||
_timer.Tick += (s, e) => UpdateSimulatedData();
|
||||
_timer.Start();
|
||||
}
|
||||
private void UpdateCurveOnUI((string name, double value) update)
|
||||
{
|
||||
var (signalName, value) = update;
|
||||
|
||||
if (!SeriesDic.TryGetValue(signalName, out var line))
|
||||
return;
|
||||
|
||||
line.Points.Add(DateTimeAxis.CreateDataPoint(DateTime.Now, value));
|
||||
}
|
||||
|
||||
private async void OnCurveDataReceived((string device, Dictionary<string, double> data) tuple)
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
var (device, data) = tuple;
|
||||
foreach (var item in data)
|
||||
{
|
||||
string propname = item.Key;
|
||||
double value = item.Value;
|
||||
string signalName = device + "." + propname;
|
||||
|
||||
if (CurSingleList.Contains(signalName))
|
||||
{
|
||||
// 通过 Progress 安全更新 UI
|
||||
_progress.Report((signalName, value));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void InitData()
|
||||
{
|
||||
SelectedSaveDays=SystemConfig.Instance.SaveDay.ToString();
|
||||
FilePath= SystemConfig.Instance.DBSavePath;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region 模拟量
|
||||
|
||||
private DispatcherTimer _timer;
|
||||
private double _time = 0;
|
||||
|
||||
private void InitializeSimulatedSignals()
|
||||
{
|
||||
CurveModel.Legends.Add(new Legend
|
||||
foreach (var _PollingRead in _devices.PollingReadDic)
|
||||
{
|
||||
LegendPosition= LegendPosition.TopLeft,
|
||||
IsLegendVisible=true
|
||||
});
|
||||
// 模拟四个信号的初始化
|
||||
string deviceName = _PollingRead.Key;
|
||||
PollingRead pollingRead = _PollingRead.Value;
|
||||
|
||||
// 模拟量1:正弦波
|
||||
var sineSignal = new LineSeries
|
||||
{
|
||||
Title = "正弦波信号",
|
||||
MarkerType = MarkerType.Circle,
|
||||
StrokeThickness = 2,
|
||||
Color = OxyColors.Red
|
||||
};
|
||||
_signalSeries.Add(sineSignal);
|
||||
SeriesDic.Add(sineSignal.Title, sineSignal);
|
||||
var props = pollingRead.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
|
||||
.Where(p => p.PropertyType == typeof(double));
|
||||
|
||||
// 模拟量2:线性增长
|
||||
var linearSignal = new LineSeries
|
||||
{
|
||||
Title = "线性增长信号",
|
||||
MarkerType = MarkerType.Square,
|
||||
StrokeThickness = 2,
|
||||
Color = OxyColors.Green
|
||||
};
|
||||
_signalSeries.Add(linearSignal);
|
||||
SeriesDic.Add(linearSignal.Title, linearSignal);
|
||||
|
||||
// 模拟量3:随机波动
|
||||
var randomSignal = new LineSeries
|
||||
{
|
||||
Title = "随机波动信号",
|
||||
MarkerType = MarkerType.Triangle,
|
||||
StrokeThickness = 2,
|
||||
Color = OxyColors.Blue
|
||||
};
|
||||
_signalSeries.Add(randomSignal);
|
||||
SeriesDic.Add(randomSignal.Title, randomSignal);
|
||||
|
||||
// 模拟量4:指数衰减
|
||||
var exponentialSignal = new LineSeries
|
||||
{
|
||||
Title = "指数衰减信号",
|
||||
MarkerType = MarkerType.Diamond,
|
||||
StrokeThickness = 2,
|
||||
Color = OxyColors.Orange
|
||||
};
|
||||
_signalSeries.Add(exponentialSignal);
|
||||
SeriesDic.Add(exponentialSignal.Title, exponentialSignal);
|
||||
|
||||
// 将模拟量曲线添加到图表中
|
||||
foreach (var signal in _signalSeries)
|
||||
{
|
||||
CurveModel.Series.Add(signal);
|
||||
foreach (var prop in props)
|
||||
{
|
||||
DeviceSingleList.Add(deviceName + "." + prop.Name);
|
||||
}
|
||||
}
|
||||
foreach(var curve in CurSingleList)
|
||||
{
|
||||
AddSignal(curve);
|
||||
}
|
||||
InitCurveModel();
|
||||
InitTimer();
|
||||
}
|
||||
private void UpdateSimulatedData()
|
||||
private void InitCurveModel()
|
||||
{
|
||||
// 更新模拟量的值并添加新的数据点
|
||||
CurveModel.Axes.Clear();
|
||||
|
||||
// 模拟量1:正弦波
|
||||
var sineSignal = _signalSeries[0];
|
||||
sineSignal.Points.Add(new DataPoint(_time, Math.Sin(_time)));
|
||||
if (sineSignal.Points.Count > 1000) sineSignal.Points.RemoveAt(0); // 保持最多100个点
|
||||
var timeAxis = new DateTimeAxis
|
||||
{
|
||||
Position = AxisPosition.Bottom,
|
||||
StringFormat = "HH:mm:ss",
|
||||
Title = "时间",
|
||||
IntervalType = DateTimeIntervalType.Seconds
|
||||
};
|
||||
CurveModel.Axes.Add(timeAxis);
|
||||
|
||||
// 模拟量2:线性增长
|
||||
var linearSignal = _signalSeries[1];
|
||||
linearSignal.Points.Add(new DataPoint(_time, _time));
|
||||
if (linearSignal.Points.Count > 1000) linearSignal.Points.RemoveAt(0); // 保持最多100个点
|
||||
|
||||
// 模拟量3:随机波动
|
||||
var randomSignal = _signalSeries[2];
|
||||
var randomValue = 10 * (2 * new Random().NextDouble() - 1); // 随机波动范围 [-10, 10]
|
||||
randomSignal.Points.Add(new DataPoint(_time, randomValue));
|
||||
if (randomSignal.Points.Count > 1000) randomSignal.Points.RemoveAt(0); // 保持最多100个点
|
||||
|
||||
// 模拟量4:指数衰减
|
||||
var exponentialSignal = _signalSeries[3];
|
||||
exponentialSignal.Points.Add(new DataPoint(_time, Math.Exp(-0.1 * _time)));
|
||||
if (exponentialSignal.Points.Count > 1000) exponentialSignal.Points.RemoveAt(0); // 保持最多100个点
|
||||
|
||||
// 更新图表
|
||||
CurveModel.InvalidatePlot(true);
|
||||
|
||||
// 时间前进
|
||||
_time += 0.5; // 每次增加0.1秒
|
||||
var valueAxis = new LinearAxis
|
||||
{
|
||||
Position = AxisPosition.Left,
|
||||
Title = "数值"
|
||||
};
|
||||
CurveModel.Axes.Add(valueAxis);
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void InitTimer()
|
||||
{
|
||||
_refreshTimer = new DispatcherTimer
|
||||
{
|
||||
Interval = TimeSpan.FromSeconds(1)
|
||||
};
|
||||
_refreshTimer.Tick += (s, e) =>
|
||||
{
|
||||
CurveModel.InvalidatePlot(true);
|
||||
};
|
||||
_refreshTimer.Start();
|
||||
}
|
||||
|
||||
|
||||
private OxyColor GetRandomColor()
|
||||
{
|
||||
// 生成随机的红色、绿色、蓝色分量,范围是 0 到 255
|
||||
@ -237,28 +217,62 @@ namespace BOB.ViewModels
|
||||
return OxyColor.FromRgb(r, g, b);
|
||||
}
|
||||
|
||||
private void AddSignal()
|
||||
private void AddSignal(string Curve="")
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_SeriesDic.ContainsKey(SelectCurve))
|
||||
if (Curve == null)
|
||||
{
|
||||
return;
|
||||
if (_SeriesDic.ContainsKey(SelectCurve))
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
var sineSignal = new LineSeries
|
||||
{
|
||||
Title = SelectCurve,
|
||||
MarkerType = MarkerType.Circle,
|
||||
StrokeThickness = 2,
|
||||
Color = GetRandomColor()
|
||||
};
|
||||
CurveModel.Series.Add(sineSignal);
|
||||
CurveModel.Legends.Add(new Legend
|
||||
{
|
||||
LegendPosition = LegendPosition.TopCenter, // 图表顶部中间
|
||||
LegendOrientation = LegendOrientation.Horizontal, // 横向排列
|
||||
LegendPlacement = LegendPlacement.Inside, // 放在图上面
|
||||
LegendBorderThickness = 0, // 去掉边框,可选
|
||||
LegendBackground = OxyColors.WhiteSmoke // 背景色,可选
|
||||
});
|
||||
|
||||
SeriesDic.Add(SelectCurve, sineSignal);
|
||||
CurSingleList.Add(SelectCurve);
|
||||
SystemConfig.Instance.SaveToFile();
|
||||
CurveModel.InvalidatePlot(true);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// 开启资源
|
||||
|
||||
var sineSignal = new LineSeries
|
||||
{
|
||||
Title = SelectCurve,
|
||||
Title = Curve,
|
||||
MarkerType = MarkerType.Circle,
|
||||
StrokeThickness = 2,
|
||||
Color = GetRandomColor()
|
||||
};
|
||||
CurveModel.Series.Add(sineSignal);
|
||||
SeriesDic.Add(SelectCurve, sineSignal);
|
||||
CurSingleList.Add(SelectCurve);
|
||||
CurveModel.Legends.Add(new Legend
|
||||
{
|
||||
LegendPosition = LegendPosition.TopCenter, // 图表顶部中间
|
||||
LegendOrientation = LegendOrientation.Horizontal, // 横向排列
|
||||
LegendPlacement = LegendPlacement.Inside, // 放在图上面
|
||||
LegendBorderThickness = 0, // 去掉边框,可选
|
||||
LegendBackground = OxyColors.WhiteSmoke // 背景色,可选
|
||||
});
|
||||
|
||||
SeriesDic.Add(Curve, sineSignal);
|
||||
CurveModel.InvalidatePlot(true);
|
||||
}
|
||||
}
|
||||
@ -277,9 +291,8 @@ namespace BOB.ViewModels
|
||||
_SeriesDic.Remove(SelectDeleteCurve);
|
||||
CurveModel.Series.Remove(signalToRemove);
|
||||
CurSingleList.Remove(SelectDeleteCurve);
|
||||
SystemConfig.Instance.SaveToFile();
|
||||
CurveModel.InvalidatePlot(true);
|
||||
|
||||
// 释放资源
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@ -176,6 +176,7 @@ namespace BOB.ViewModels
|
||||
}
|
||||
break;
|
||||
}
|
||||
_eventAggregator.GetEvent<ConnectionChangeEvent>().Publish((DeviceList[i].Remark, isConnected));
|
||||
}
|
||||
|
||||
progress.Report((i, isConnected));
|
||||
|
||||
@ -145,7 +145,7 @@ namespace BOB.ViewModels
|
||||
break;
|
||||
|
||||
case "更新信息":
|
||||
|
||||
_regionManager.RequestNavigate("ShellViewManager", "UpdateInfoView");
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
46
BOB/ViewModels/UpdateInfoViewModel.cs
Normal file
46
BOB/ViewModels/UpdateInfoViewModel.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using Model;
|
||||
using Newtonsoft.Json;
|
||||
using Prism.Mvvm;
|
||||
using Prism.Ioc;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace BOB.ViewModels
|
||||
{
|
||||
public class UpdateInfoViewModel : BindableBase
|
||||
{
|
||||
private List<UpdateInfoModel> _updateList;
|
||||
public List<UpdateInfoModel> UpdateList
|
||||
{
|
||||
get => _updateList;
|
||||
set => SetProperty(ref _updateList, value);
|
||||
}
|
||||
|
||||
public UpdateInfoViewModel(IContainerProvider containerProvider)
|
||||
{
|
||||
string path = Path.Combine(SystemConfig.Instance.SystemPath, "UpdateInfo.json");
|
||||
|
||||
if (File.Exists(path))
|
||||
{
|
||||
try
|
||||
{
|
||||
string json = File.ReadAllText(path, Encoding.UTF8);
|
||||
UpdateList = JsonConvert.DeserializeObject<List<UpdateInfoModel>>(json)
|
||||
?? new List<UpdateInfoModel>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UpdateList = new List<UpdateInfoModel>();
|
||||
Console.WriteLine("读取 UpdateInfo.json 出错: " + ex.Message);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
UpdateList = new List<UpdateInfoModel>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -9,6 +9,7 @@
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
mc:Ignorable="d"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
xmlns:ucs="clr-namespace:BOB.Views.UserControls"
|
||||
Background="White"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
Height="850"
|
||||
@ -27,7 +28,6 @@
|
||||
<!-- 实时监控 -->
|
||||
<GroupBox x:Name="实时监控区"
|
||||
Header="实时监控"
|
||||
Grid.Column="1"
|
||||
Padding="0,0,0,0">
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
@ -35,7 +35,12 @@
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<ucs:NumericalDisplay DataContext="{Binding 电压MV,Mode=TwoWay}"
|
||||
Grid.Column="0" />
|
||||
<ucs:NumericalDisplay DataContext="{Binding 电流MV,Mode=TwoWay}"
|
||||
Grid.Column="1" />
|
||||
<ucs:NumericalDisplay DataContext="{Binding 功率MV,Mode=TwoWay}"
|
||||
Grid.Column="2" />
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
@ -43,7 +48,14 @@
|
||||
<GroupBox Header="实时曲线"
|
||||
Grid.Row="1"
|
||||
Padding="0,0,0,0">
|
||||
<oxy:PlotView Model="{Binding 曲线Model}" />
|
||||
<oxy:PlotView Model="{Binding 曲线Model}">
|
||||
<oxy:PlotView.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="视图复位"
|
||||
Command="{Binding ResetViewCommand}" />
|
||||
</ContextMenu>
|
||||
</oxy:PlotView.ContextMenu>
|
||||
</oxy:PlotView>
|
||||
</GroupBox>
|
||||
|
||||
<!-- 调试选项 -->
|
||||
|
||||
@ -50,7 +50,14 @@
|
||||
<GroupBox Header="实时曲线"
|
||||
Grid.Row="1"
|
||||
Padding="0,0,0,0">
|
||||
<oxy:PlotView Model="{Binding 曲线Model}" />
|
||||
<oxy:PlotView Model="{Binding 曲线Model}">
|
||||
<oxy:PlotView.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="视图复位"
|
||||
Command="{Binding ResetViewCommand}" />
|
||||
</ContextMenu>
|
||||
</oxy:PlotView.ContextMenu>
|
||||
</oxy:PlotView>
|
||||
</GroupBox>
|
||||
|
||||
<!-- 调试选项 -->
|
||||
|
||||
@ -15,8 +15,10 @@
|
||||
<Style BasedOn="{StaticResource DialogUserManageStyle}"
|
||||
TargetType="Window" />
|
||||
</prism:Dialog.WindowStyle>
|
||||
<Grid MouseLeftButtonDown="MouseLeftButtonDown">
|
||||
<TreeView Margin="10">
|
||||
<GroupBox Header="IO板卡手动设置"
|
||||
Padding="0,0,0,0">
|
||||
<Grid MouseLeftButtonDown="MouseLeftButtonDown">
|
||||
<TreeView Margin="10">
|
||||
<TreeViewItem Header="连接状态设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="连接"
|
||||
@ -74,13 +76,14 @@
|
||||
</TreeViewItem>
|
||||
</TreeViewItem>
|
||||
</TreeView>
|
||||
<StackPanel Grid.Row="2"
|
||||
VerticalAlignment="Bottom">
|
||||
<Button Content="关闭"
|
||||
Width="70"
|
||||
Margin="10"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{Binding CloseCommand}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<StackPanel Grid.Row="2"
|
||||
VerticalAlignment="Bottom">
|
||||
<Button Content="关闭"
|
||||
Width="70"
|
||||
Margin="10"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{Binding CloseCommand}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
</UserControl>
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:BOB.Views.Dialogs"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:ucs="clr-namespace:BOB.Views.UserControls"
|
||||
mc:Ignorable="d"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
@ -26,15 +27,34 @@
|
||||
|
||||
<GroupBox x:Name="实时监控区"
|
||||
Header="实时监控"
|
||||
Grid.Row="0"
|
||||
Padding="0,0,0,0">
|
||||
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ucs:NumericalDisplay DataContext="{Binding 电压MV,Mode=TwoWay}"
|
||||
Grid.Column="0" />
|
||||
<ucs:NumericalDisplay DataContext="{Binding 电流MV,Mode=TwoWay}"
|
||||
Grid.Column="1" />
|
||||
<ucs:NumericalDisplay DataContext="{Binding 功率MV,Mode=TwoWay}"
|
||||
Grid.Column="2" />
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<!-- 实时曲线 -->
|
||||
<GroupBox Header="实时曲线"
|
||||
Grid.Row="1"
|
||||
Padding="0,0,0,0">
|
||||
<oxy:PlotView Model="{Binding 曲线Model}" />
|
||||
<oxy:PlotView Model="{Binding 曲线Model}">
|
||||
<oxy:PlotView.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="视图复位"
|
||||
Command="{Binding ResetViewCommand}" />
|
||||
</ContextMenu>
|
||||
</oxy:PlotView.ContextMenu>
|
||||
</oxy:PlotView>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="调试选项"
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:BOB.Views.Dialogs"
|
||||
xmlns:oxy="http://oxyplot.org/wpf"
|
||||
xmlns:ucs="clr-namespace:BOB.Views.UserControls"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
mc:Ignorable="d"
|
||||
@ -26,15 +27,33 @@
|
||||
|
||||
<GroupBox x:Name="实时监控区"
|
||||
Header="实时监控"
|
||||
Grid.Column="1"
|
||||
Padding="0,0,0,0">
|
||||
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ucs:NumericalDisplay DataContext="{Binding 电压MV,Mode=TwoWay}"
|
||||
Grid.Column="0" />
|
||||
<ucs:NumericalDisplay DataContext="{Binding 电流MV,Mode=TwoWay}"
|
||||
Grid.Column="1" />
|
||||
<ucs:NumericalDisplay DataContext="{Binding 功率MV,Mode=TwoWay}"
|
||||
Grid.Column="2" />
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="实时曲线"
|
||||
Grid.Row="1"
|
||||
Padding="0,0,0,0">
|
||||
<oxy:PlotView Model="{Binding 曲线Model}" />
|
||||
<oxy:PlotView Model="{Binding 曲线Model}">
|
||||
<oxy:PlotView.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="视图复位"
|
||||
Command="{Binding ResetViewCommand}" />
|
||||
</ContextMenu>
|
||||
</oxy:PlotView.ContextMenu>
|
||||
</oxy:PlotView>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="调试选项"
|
||||
|
||||
@ -16,52 +16,102 @@
|
||||
<Style BasedOn="{StaticResource DialogUserManageStyle}"
|
||||
TargetType="Window" />
|
||||
</prism:Dialog.WindowStyle>
|
||||
<Grid MouseLeftButtonDown="MouseLeftButtonDown">
|
||||
<TreeView Margin="10">
|
||||
<TreeViewItem Header="连接状态设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="连接"
|
||||
Margin="5"
|
||||
Command="{Binding ConnectCommand}" />
|
||||
<Button Content="断开"
|
||||
Margin="5"
|
||||
Command="{Binding DisconnectCommand}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
<TreeViewItem Header="电压开关设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="开启"
|
||||
Margin="5"
|
||||
Command="{Binding OpenPowerSupplyCommand}" />
|
||||
<Button Content="关闭"
|
||||
Margin="5"
|
||||
Command="{Binding ClosePowerSupplyCommand}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
<GroupBox Header="AC源手动设置"
|
||||
Padding="0,0,0,0">
|
||||
<Grid MouseLeftButtonDown="MouseLeftButtonDown">
|
||||
<TreeView Margin="10">
|
||||
<TreeViewItem Header="连接状态设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="连接"
|
||||
Margin="5"
|
||||
Command="{Binding ConnectCommand}" />
|
||||
<Button Content="断开"
|
||||
Margin="5"
|
||||
Command="{Binding DisconnectCommand}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
<TreeViewItem Header="电压开关设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="开启"
|
||||
Margin="5"
|
||||
Command="{Binding OpenPowerSupplyCommand}" />
|
||||
<Button Content="关闭"
|
||||
Margin="5"
|
||||
Command="{Binding ClosePowerSupplyCommand}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
|
||||
<TreeViewItem Header="设置">
|
||||
<TreeViewItem Header="设定三相电压输出">
|
||||
<TreeViewItem Header="设定三相电压档位">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="低档"
|
||||
Margin="5"
|
||||
Command="{Binding SetVoltageLevelLowCommand}" />
|
||||
<Button Content="高档"
|
||||
Margin="5"
|
||||
Command="{Binding SetVoltageLevelHighCommand}" />
|
||||
</StackPanel>
|
||||
<TreeViewItem Header="设置">
|
||||
<TreeViewItem Header="设定三相电压输出">
|
||||
<TreeViewItem Header="设定三相电压档位">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="低档"
|
||||
Margin="5"
|
||||
Command="{Binding SetVoltageLevelLowCommand}" />
|
||||
<Button Content="高档"
|
||||
Margin="5"
|
||||
Command="{Binding SetVoltageLevelHighCommand}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
|
||||
<TreeViewItem Header="输出">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<Button Content="设定三相输出电压"
|
||||
Margin="5"
|
||||
Command="{Binding SetThreePhaseVoltageCommand}" />
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Label Content="U相输出电压"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding UPhaseVoltage}"
|
||||
MinWidth="50"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="V"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Label Content="V相输出电压"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding VPhaseVoltage}"
|
||||
MinWidth="50"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="V"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Label Content="W相输出电压"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding WPhaseVoltage}"
|
||||
MinWidth="50"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="V"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
</TreeViewItem>
|
||||
|
||||
<TreeViewItem Header="输出">
|
||||
<TreeViewItem Header="设定通用功能输出">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<Button Content="设定三相输出电压"
|
||||
Margin="5"
|
||||
Command="{Binding SetThreePhaseVoltageCommand}" />
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Label Content="U相输出电压"
|
||||
<Button Content="设定通用功能输出电压"
|
||||
Margin="5"
|
||||
Command="{Binding SetCommonOutputVoltageCommand}" />
|
||||
<Label Content="输出电压"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding UPhaseVoltage}"
|
||||
<TextBox Text="{Binding CommonOutputVoltage}"
|
||||
MinWidth="50"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
Margin="5"
|
||||
@ -71,134 +121,87 @@
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Label Content="V相输出电压"
|
||||
<Button Content="设定通用功能输出频率"
|
||||
Margin="5"
|
||||
Command="{Binding SetCommonOutputFrequencyCommand}" />
|
||||
<Label Content="输出频率"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding VPhaseVoltage}"
|
||||
<TextBox Text="{Binding CommonOutputFrequency}"
|
||||
MinWidth="50"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="V"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Label Content="W相输出电压"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding WPhaseVoltage}"
|
||||
MinWidth="50"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="V"
|
||||
<Label Content="Hz"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
</TreeViewItem>
|
||||
|
||||
<TreeViewItem Header="设定通用功能输出">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设定通用功能输出电压"
|
||||
Margin="5"
|
||||
Command="{Binding SetCommonOutputVoltageCommand}" />
|
||||
<Label Content="输出电压"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding CommonOutputVoltage}"
|
||||
MinWidth="50"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="V"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TreeViewItem Header="设定步阶功能输出">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设定步阶功能输出电压"
|
||||
Margin="5"
|
||||
Command="{Binding SetStepOutputVoltageCommand}" />
|
||||
<Label Content="组号"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding StepOutputVoltageGroup}"
|
||||
MinWidth="50"
|
||||
Margin="5"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="输出电压"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding StepOutputVoltage}"
|
||||
MinWidth="50"
|
||||
Margin="5"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="V"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设定步阶功能输出频率"
|
||||
Margin="5"
|
||||
Command="{Binding SetStepOutputFrequencyCommand}" />
|
||||
<Label Content="组号"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding StepOutputFrequencyGroup}"
|
||||
MinWidth="50"
|
||||
Margin="5"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="输出频率"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding StepOutputFrequency}"
|
||||
MinWidth="50"
|
||||
Margin="5"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="Hz"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设定通用功能输出频率"
|
||||
Margin="5"
|
||||
Command="{Binding SetCommonOutputFrequencyCommand}" />
|
||||
<Label Content="输出频率"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding CommonOutputFrequency}"
|
||||
MinWidth="50"
|
||||
Margin="5"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="Hz"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
</TreeViewItem>
|
||||
|
||||
<TreeViewItem Header="设定步阶功能输出">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设定步阶功能输出电压"
|
||||
Margin="5"
|
||||
Command="{Binding SetStepOutputVoltageCommand}" />
|
||||
<Label Content="组号"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding StepOutputVoltageGroup}"
|
||||
MinWidth="50"
|
||||
Margin="5"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="输出电压"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding StepOutputVoltage}"
|
||||
MinWidth="50"
|
||||
Margin="5"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="V"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设定步阶功能输出频率"
|
||||
Margin="5"
|
||||
Command="{Binding SetStepOutputFrequencyCommand}" />
|
||||
<Label Content="组号"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding StepOutputFrequencyGroup}"
|
||||
MinWidth="50"
|
||||
Margin="5"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="输出频率"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding StepOutputFrequency}"
|
||||
MinWidth="50"
|
||||
Margin="5"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="Hz"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
|
||||
</TreeViewItem>
|
||||
</TreeView>
|
||||
<StackPanel Grid.Row="2"
|
||||
VerticalAlignment="Bottom">
|
||||
<Button Content="关闭"
|
||||
Width="70"
|
||||
Margin="10"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{Binding CloseCommand}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</TreeView>
|
||||
<StackPanel Grid.Row="2"
|
||||
VerticalAlignment="Bottom">
|
||||
<Button Content="关闭"
|
||||
Width="70"
|
||||
Margin="10"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{Binding CloseCommand}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
</UserControl>
|
||||
|
||||
@ -16,56 +16,59 @@
|
||||
<Style BasedOn="{StaticResource DialogUserManageStyle}"
|
||||
TargetType="Window" />
|
||||
</prism:Dialog.WindowStyle>
|
||||
<Grid MouseLeftButtonDown="MouseLeftButtonDown">
|
||||
<TreeView Margin="10">
|
||||
<TreeViewItem Header="连接状态设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="连接"
|
||||
Margin="5"
|
||||
Command="{Binding ConnectCommand}" />
|
||||
<Button Content="断开"
|
||||
Margin="5"
|
||||
Command="{Binding DisconnectCommand}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
<GroupBox Header="AC载手动设置"
|
||||
Padding="0,0,0,0">
|
||||
<Grid MouseLeftButtonDown="MouseLeftButtonDown">
|
||||
<TreeView Margin="10">
|
||||
<TreeViewItem Header="连接状态设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="连接"
|
||||
Margin="5"
|
||||
Command="{Binding ConnectCommand}" />
|
||||
<Button Content="断开"
|
||||
Margin="5"
|
||||
Command="{Binding DisconnectCommand}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
|
||||
<TreeViewItem Header="上下载设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="加载"
|
||||
Margin="5"
|
||||
Command="{Binding LoadCommand}" />
|
||||
<Button Content="卸载"
|
||||
Margin="5"
|
||||
Command="{Binding UnloadCommand}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
<TreeViewItem Header="上下载设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="加载"
|
||||
Margin="5"
|
||||
Command="{Binding LoadCommand}" />
|
||||
<Button Content="卸载"
|
||||
Margin="5"
|
||||
Command="{Binding UnloadCommand}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
|
||||
<TreeViewItem Header="功率设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="读取功率"
|
||||
Margin="5"
|
||||
Command="{Binding ReadPowerCommand}" />
|
||||
<Button Content="设置功率"
|
||||
Margin="5"
|
||||
Command="{Binding SetPowerCommand}" />
|
||||
<Label Content="功率"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding CurrentPowerDisplay}"
|
||||
MinWidth="100"
|
||||
Margin="5"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
</TreeView>
|
||||
<StackPanel Grid.Row="2"
|
||||
VerticalAlignment="Bottom">
|
||||
<Button Content="关闭"
|
||||
Width="70"
|
||||
Margin="10"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{Binding CloseCommand}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<TreeViewItem Header="功率设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="读取功率"
|
||||
Margin="5"
|
||||
Command="{Binding ReadPowerCommand}" />
|
||||
<Button Content="设置功率"
|
||||
Margin="5"
|
||||
Command="{Binding SetPowerCommand}" />
|
||||
<Label Content="功率"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding CurrentPowerDisplay}"
|
||||
MinWidth="100"
|
||||
Margin="5"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
</TreeView>
|
||||
<StackPanel Grid.Row="2"
|
||||
VerticalAlignment="Bottom">
|
||||
<Button Content="关闭"
|
||||
Width="70"
|
||||
Margin="10"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{Binding CloseCommand}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
</UserControl>
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
<UserControl x:Class="BOB.Views.ProgressView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:BOB.Views"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800">
|
||||
<Grid Background="Transparent">
|
||||
<StackPanel Width="150"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0 0 0 100"
|
||||
>
|
||||
<ProgressBar Width="80"
|
||||
Height="80"
|
||||
Margin="20"
|
||||
IsIndeterminate="True"
|
||||
Style="{StaticResource MaterialDesignCircularProgressBar}" />
|
||||
<TextBlock FontSize="30" Text="加载中......" HorizontalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -252,20 +252,25 @@
|
||||
Identifier="Root">
|
||||
<!-- 主内容区 -->
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="29*" />
|
||||
<ColumnDefinition Width="424*" />
|
||||
<ColumnDefinition Width="91*" />
|
||||
<ColumnDefinition Width="57*" />
|
||||
<ColumnDefinition Width="1318*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ContentControl prism:RegionManager.RegionName="ShellViewManager"
|
||||
Grid.ColumnSpan="5" />
|
||||
/>
|
||||
<Border x:Name="Overlay"
|
||||
Background="#40000000"
|
||||
Visibility="Collapsed"
|
||||
Panel.ZIndex="10"
|
||||
Grid.ColumnSpan="5" />
|
||||
Panel.ZIndex="1">
|
||||
<StackPanel Width="150"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0 0 0 100">
|
||||
<ProgressBar Width="80"
|
||||
Height="80"
|
||||
Margin="20"
|
||||
IsIndeterminate="True"
|
||||
Style="{StaticResource MaterialDesignCircularProgressBar}" />
|
||||
<TextBlock FontSize="30"
|
||||
Text="加载中......"
|
||||
HorizontalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
</materialDesign:DialogHost>
|
||||
</Grid>
|
||||
|
||||
@ -26,8 +26,6 @@ namespace BOB.Views
|
||||
public ShellView(IEventAggregator eventAggregator)
|
||||
{
|
||||
InitializeComponent();
|
||||
//注册等待消息窗口
|
||||
eventAggregator.GetEvent<WaitingEvent>().Subscribe(ShowWaiting);
|
||||
//注册灰度遮罩层
|
||||
eventAggregator.GetEvent<OverlayEvent>().Subscribe(ShowOverlay);
|
||||
}
|
||||
@ -36,13 +34,7 @@ namespace BOB.Views
|
||||
{
|
||||
Overlay.Visibility = arg ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
private void ShowWaiting(bool arg)
|
||||
{
|
||||
DialogHost.IsOpen = arg;
|
||||
|
||||
if (DialogHost.IsOpen)
|
||||
DialogHost.DialogContent = new ProgressView();
|
||||
}
|
||||
|
||||
private void ColorZone_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
|
||||
30
BOB/Views/UpdateInfoView.xaml
Normal file
30
BOB/Views/UpdateInfoView.xaml
Normal file
@ -0,0 +1,30 @@
|
||||
<UserControl x:Class="BOB.Views.UpdateInfoView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid Margin="20">
|
||||
<ListView ItemsSource="{Binding UpdateList}">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Margin="5"
|
||||
Orientation="Vertical">
|
||||
<TextBlock Text="{Binding Time}"
|
||||
FontWeight="Bold"
|
||||
Foreground="#673ab7" />
|
||||
<TextBlock Text="{Binding Message}"
|
||||
TextWrapping="Wrap"
|
||||
Margin="0,3,0,10" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
@ -10,16 +10,17 @@ using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BOB.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// ProgressView.xaml 的交互逻辑
|
||||
/// UpdateInfoView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class ProgressView : UserControl
|
||||
public partial class UpdateInfoView : UserControl
|
||||
{
|
||||
public ProgressView()
|
||||
public UpdateInfoView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
@ -38,7 +38,7 @@
|
||||
|
||||
<!-- 温度 -->
|
||||
<Viewbox Grid.Row="1">
|
||||
<TextBlock Text="{Binding Temperature, StringFormat='0.00'}"
|
||||
<TextBlock Text="{Binding MonitorValue, StringFormat='0.00'}"
|
||||
FontSize="40"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{Binding TextColor}"
|
||||
|
||||
12
Common/PubEvent/ChangeCurrentTagEvent.cs
Normal file
12
Common/PubEvent/ChangeCurrentTagEvent.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Common.PubEvent
|
||||
{
|
||||
public class ChangeCurrentTagEvent:PubSubEvent<string>
|
||||
{
|
||||
}
|
||||
}
|
||||
12
Common/PubEvent/ConnectionChangeEvent.cs
Normal file
12
Common/PubEvent/ConnectionChangeEvent.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Common.PubEvent
|
||||
{
|
||||
public class ConnectionChangeEvent:PubSubEvent<(string,bool)>
|
||||
{
|
||||
}
|
||||
}
|
||||
13
Common/PubEvent/CurveDataEvent.cs
Normal file
13
Common/PubEvent/CurveDataEvent.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Common.PubEvent
|
||||
{
|
||||
public class CurveDataEvent:PubSubEvent<(string, Dictionary<string,double>)>
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
12
Common/PubEvent/StartProcessEvent.cs
Normal file
12
Common/PubEvent/StartProcessEvent.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Common.PubEvent
|
||||
{
|
||||
public class StartProcessEvent:PubSubEvent<(string,bool)>
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -174,6 +174,43 @@ namespace DeviceCommand.Device
|
||||
else if (CurrentDevice == "IT6724CReverse")
|
||||
await _IT6724CReverse.发送自定义命令(指令, ct);
|
||||
}
|
||||
public virtual async Task<double> 查询实时电压(CancellationToken ct = default)
|
||||
{
|
||||
double value = 0;
|
||||
|
||||
if (CurrentDevice == "E36233A")
|
||||
value = await _E36233A.查询电压(ct);
|
||||
else if (CurrentDevice == "IT6724CReverse")
|
||||
value = await _IT6724CReverse.查询实时电压(ct);
|
||||
|
||||
return Math.Round(value, 1);
|
||||
}
|
||||
|
||||
public virtual async Task<double> 查询实时电流(CancellationToken ct = default)
|
||||
{
|
||||
double value = 0;
|
||||
|
||||
if (CurrentDevice == "E36233A")
|
||||
value = await _E36233A.查询电流(ct);
|
||||
else if (CurrentDevice == "IT6724CReverse")
|
||||
value = await _IT6724CReverse.查询实时电流(ct);
|
||||
|
||||
return Math.Round(value, 1);
|
||||
}
|
||||
|
||||
public virtual async Task<double> 查询实时功率(CancellationToken ct = default)
|
||||
{
|
||||
double value = 0;
|
||||
|
||||
if (CurrentDevice == "E36233A")
|
||||
value = await _E36233A.查询功率(ct);
|
||||
else if (CurrentDevice == "IT6724CReverse")
|
||||
value = await _IT6724CReverse.查询实时功率(ct);
|
||||
|
||||
return Math.Round(value, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@ -115,87 +115,146 @@ namespace DeviceCommand.Device
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region 设置命令
|
||||
#region 设置命令(不自动切换通道)
|
||||
|
||||
/// <summary>
|
||||
/// 设置当前操作通道
|
||||
/// </summary>
|
||||
public async Task 设置通道(int 通道, CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync($"INST:NSEL {通道}\n", ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询当前通道
|
||||
/// </summary>
|
||||
public async Task<string> 查询当前通道(CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync("INST:NSEL?\n", ct);
|
||||
return await ReadAsync(ct: ct);
|
||||
}
|
||||
|
||||
public async Task 清除输出保护(CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync($"PROTection:CLEar\r\n", ct);
|
||||
await SendAsync("OUTP:PROT:CLE\n", ct);
|
||||
}
|
||||
|
||||
public async Task 设置电源输出(bool 开关, CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync($"OUTPut {(开关 ? 1 : 0)}\r\n", ct);
|
||||
await SendAsync($"OUTP {(开关 ? "ON" : "OFF")}\n", ct);
|
||||
}
|
||||
|
||||
public async Task 设置为远程模式(CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync($"SYSTem:REMote\r\n", ct);
|
||||
await SendAsync("SYST:REM\n", ct);
|
||||
}
|
||||
|
||||
public async Task 蜂鸣器测试(CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync($"SYSTem:BEEPer\r\n", ct);
|
||||
await SendAsync("SYST:BEEP\n", ct);
|
||||
}
|
||||
|
||||
public async Task 设置电流(double 电流, CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync($"CURRent {电流}\r\n", ct);
|
||||
await SendAsync($"CURR {电流}\n", ct);
|
||||
}
|
||||
|
||||
public async Task 设置电流保护OCP电流(double 电流, CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync($"CURRent:PROTection {电流}\r\n", ct);
|
||||
await SendAsync($"CURR:PROT {电流}\n", ct);
|
||||
}
|
||||
|
||||
public async Task 设置OCP开关(bool 开关, CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync($"CURRent:PROTection:STATe {(开关 ? 1 : 0)}\r\n", ct);
|
||||
await SendAsync($"CURR:PROT:STAT {(开关 ? "ON" : "OFF")}\n", ct);
|
||||
}
|
||||
|
||||
public async Task 设置电压(double 电压, CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync($"VOLTage {电压}\r\n", ct);
|
||||
await SendAsync($"VOLT {电压}\n", ct);
|
||||
}
|
||||
|
||||
public async Task 设置电压保护OVP电压(double 电压, CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync($"VOLT:PROTection {电压}\r\n", ct);
|
||||
await SendAsync($"VOLT:PROT {电压}\n", ct);
|
||||
}
|
||||
|
||||
public async Task 设置OVP开关(bool 开关, CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync($"VOLT:PROTection:STATe {(开关 ? 1 : 0)}\r\n", ct);
|
||||
await SendAsync($"VOLT:PROT:STAT {(开关 ? "ON" : "OFF")}\n", ct);
|
||||
}
|
||||
|
||||
public async Task 设置功率保护功率(double 电压, CancellationToken ct = default)
|
||||
public async Task 设置功率保护功率(double 功率值, CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync($"POWer:PROTection {电压}\r\n", ct);
|
||||
await SendAsync($"POW:PROT {功率值}\n", ct);
|
||||
}
|
||||
|
||||
public async Task 设置功率保护开关(bool 开关, CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync($"POWer:PROTection:STATe {(开关 ? 1 : 0)}\r\n", ct);
|
||||
await SendAsync($"POW:PROT:STAT {(开关 ? "ON" : "OFF")}\n", ct);
|
||||
}
|
||||
|
||||
public async Task 设置电流斜率(double 上升斜率, double 下降斜率, CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync($"CURRent:SLEW {上升斜率},{下降斜率}\r\n", ct);
|
||||
await SendAsync($"CURR:SLEW:UP {上升斜率}\n", ct);
|
||||
await SendAsync($"CURR:SLEW:DOWN {下降斜率}\n", ct);
|
||||
}
|
||||
|
||||
public async Task 设置电压斜率(double 上升斜率, double 下降斜率, CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync($"VOLTage:SLEW {上升斜率},{下降斜率}\r\n", ct);
|
||||
await SendAsync($"VOLT:SLEW:UP {上升斜率}\n", ct);
|
||||
await SendAsync($"VOLT:SLEW:DOWN {下降斜率}\n", ct);
|
||||
}
|
||||
|
||||
public async Task 发送自定义命令(string 指令, CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync($"{指令}\r\n", ct);
|
||||
await SendAsync($"{指令}\n", ct);
|
||||
}
|
||||
public virtual async Task<string> 查询设备信息(CancellationToken ct = default)
|
||||
|
||||
/// <summary>
|
||||
/// 查询设备基本信息
|
||||
/// </summary>
|
||||
public async Task<string> 查询设备信息(CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync("*IDN?\r\n", ct);
|
||||
await SendAsync("*IDN?\n", ct);
|
||||
return await ReadAsync(ct: ct);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 查询命令
|
||||
|
||||
/// <summary>
|
||||
/// 查询当前电压测量值
|
||||
/// </summary>
|
||||
public async Task<double> 查询电压(CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync("MEAS:VOLT?\n", ct);
|
||||
string result = await ReadAsync(ct: ct);
|
||||
return double.Parse(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询当前电流测量值
|
||||
/// </summary>
|
||||
public async Task<double> 查询电流(CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync("MEAS:CURR?\n", ct);
|
||||
string result = await ReadAsync(ct: ct);
|
||||
return double.Parse(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询当前功率测量值
|
||||
/// </summary>
|
||||
public async Task<double> 查询功率(CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync("MEAS:POW?\n", ct);
|
||||
string result = await ReadAsync(ct: ct);
|
||||
return double.Parse(result);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ namespace DeviceCommand.Device
|
||||
|
||||
public override async Task<bool> ConnectAsync(CancellationToken ct = default)
|
||||
{
|
||||
await commLock.WaitAsync(ct);
|
||||
try
|
||||
{
|
||||
if (SerialPort.IsOpen)
|
||||
@ -48,7 +49,7 @@ namespace DeviceCommand.Device
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
commLock.Release();
|
||||
}
|
||||
}
|
||||
public override void Close()
|
||||
|
||||
@ -25,6 +25,7 @@ namespace DeviceCommand.Device
|
||||
|
||||
public override async Task<bool> ConnectAsync(CancellationToken ct = default)
|
||||
{
|
||||
await commLock.WaitAsync(ct);
|
||||
try
|
||||
{
|
||||
if (SerialPort.IsOpen)
|
||||
@ -46,7 +47,7 @@ namespace DeviceCommand.Device
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
commLock.Release();
|
||||
}
|
||||
}
|
||||
public override void Close()
|
||||
@ -171,7 +172,35 @@ namespace DeviceCommand.Device
|
||||
await SendAsync("*IDN?\r\n", ct);
|
||||
return await ReadAsync(ct: ct);
|
||||
}
|
||||
/// <summary>
|
||||
/// 查询实际输出电流(单位:A)
|
||||
/// </summary>
|
||||
public virtual async Task<double> 查询实时电流(CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync("MEASure:CURRent?\r\n", ct);
|
||||
var result = await ReadAsync(ct: ct);
|
||||
return Convert.ToDouble(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询实际输出电压(单位:V)
|
||||
/// </summary>
|
||||
public virtual async Task<double> 查询实时电压(CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync("MEASure:VOLTage?\r\n", ct);
|
||||
var result = await ReadAsync(ct: ct);
|
||||
return Convert.ToDouble(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询实际输出功率(单位:W)
|
||||
/// </summary>
|
||||
public virtual async Task<double> 查询实时功率(CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync("MEASure:POWer?\r\n", ct);
|
||||
var result = await ReadAsync(ct: ct);
|
||||
return Convert.ToDouble(result);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
14
Model/UpdateInfoModel.cs
Normal file
14
Model/UpdateInfoModel.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Model
|
||||
{
|
||||
public class UpdateInfoModel
|
||||
{
|
||||
public string Message { get; set; }
|
||||
public string Time { get; set; }
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,7 @@ using BOB.Views;
|
||||
using BOB.Views.Dialogs;
|
||||
using Prism.Ioc;
|
||||
using ProcessManager.ViewModels;
|
||||
using ProcessManager.Views;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Windows;
|
||||
@ -23,12 +24,18 @@ namespace ProcessManager
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
|
||||
var regionManager = Container.Resolve<IRegionManager>();
|
||||
regionManager.RequestNavigate("MainRegion", "Menu");
|
||||
|
||||
}
|
||||
protected override void RegisterTypes(IContainerRegistry containerRegistry)
|
||||
{
|
||||
containerRegistry.RegisterForNavigation<MainWindow, PMainViewModel>();
|
||||
containerRegistry.RegisterForNavigation<MenuView, MenuViewModel>("Menu");
|
||||
containerRegistry.RegisterForNavigation<DevicesView, DevicesViewModel>("DeviceOne");
|
||||
containerRegistry.RegisterForNavigation<DeviceTwoView, DevicesViewModel>("DeviceTwo");
|
||||
containerRegistry.RegisterForNavigation<DeviceThreeView, DevicesViewModel>("DeviceThree");
|
||||
containerRegistry.RegisterForNavigation<DeviceOther, DevicesViewModel>("Other");
|
||||
containerRegistry.RegisterDialog<Setting, SettingViewModel>("Setting");
|
||||
}
|
||||
|
||||
|
||||
@ -8,8 +8,24 @@
|
||||
<UseWPF>true</UseWPF>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<COMReference Include="{215d64d2-031c-33c7-96e3-61794cd1ee61}">
|
||||
<WrapperTool>tlbimp</WrapperTool>
|
||||
<VersionMinor>0</VersionMinor>
|
||||
<VersionMajor>2</VersionMajor>
|
||||
<Guid>215d64d2-031c-33c7-96e3-61794cd1ee61</Guid>
|
||||
</COMReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BOB\BOB.csproj" />
|
||||
<FrameworkReference Include="Microsoft.WindowsDesktop.App.WindowsForms" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="WindowsFormsIntegration">
|
||||
<HintPath>..\..\..\WindowsFormsIntegration.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
73
ProcessManager/ViewModels/DevicesViewModel.cs
Normal file
73
ProcessManager/ViewModels/DevicesViewModel.cs
Normal file
@ -0,0 +1,73 @@
|
||||
using Common.PubEvent;
|
||||
using OxyPlot;
|
||||
using ProcessManager.Helpers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace ProcessManager.ViewModels
|
||||
{
|
||||
public class DevicesViewModel:BindableBase,INavigationAware
|
||||
{
|
||||
public ICommand WindowLoadedCommand { get; set; }
|
||||
public IEventAggregator _eventAggregator { get; set; }
|
||||
public string Title { get; set; }
|
||||
private UserControl? _currentView;
|
||||
private System.Windows.Forms.Panel? _host;
|
||||
|
||||
public DevicesViewModel(IContainerProvider containerProvider)
|
||||
{
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
_eventAggregator.GetEvent<StartProcessEvent>().Subscribe(GetProcess);
|
||||
WindowLoadedCommand =new DelegateCommand(OnWindowLoaded);
|
||||
}
|
||||
|
||||
private void GetProcess((string exeName, bool isStart) msg)
|
||||
{
|
||||
if(Title!= msg.exeName) return;
|
||||
if (_currentView == null) return;
|
||||
if (!msg.isStart) return;
|
||||
WindowEmbedHelper.FindAndEmbedWindow(msg.exeName, _host);
|
||||
}
|
||||
|
||||
private void OnWindowLoaded()
|
||||
{
|
||||
|
||||
}
|
||||
#region 导航
|
||||
public bool IsNavigationTarget(NavigationContext navigationContext)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnNavigatedFrom(NavigationContext navigationContext)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
Title= navigationContext.Parameters.GetValue<string>("Title");
|
||||
string viewName = navigationContext.Parameters.GetValue<string>("viewName");
|
||||
_currentView = navigationContext.NavigationService.Region .ActiveViews .FirstOrDefault() as UserControl;
|
||||
if (_currentView != null)
|
||||
{
|
||||
// 反射拿 Host 属性
|
||||
var hostProp = _currentView.GetType().GetProperty("Host");
|
||||
_host = hostProp?.GetValue(_currentView) as System.Windows.Forms.Panel;
|
||||
}
|
||||
_eventAggregator.GetEvent<ChangeCurrentTagEvent>()
|
||||
.Publish(!string.IsNullOrEmpty(viewName) ? viewName : Title);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
163
ProcessManager/ViewModels/MenuViewModel.cs
Normal file
163
ProcessManager/ViewModels/MenuViewModel.cs
Normal file
@ -0,0 +1,163 @@
|
||||
using Azure;
|
||||
using BOB;
|
||||
using Common.PubEvent;
|
||||
using ProcessManager.Helpers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace ProcessManager.ViewModels
|
||||
{
|
||||
public class MenuViewModel : BindableBase, INavigationAware
|
||||
{
|
||||
private ObservableCollection<SystemConfig> _configList;
|
||||
|
||||
public ObservableCollection<SystemConfig> ConfigList
|
||||
{
|
||||
get => _configList;
|
||||
set => SetProperty(ref _configList, value);
|
||||
}
|
||||
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IRegionManager _regionManager;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private Dictionary<string, Process> ProcessDic { get; set; } = new Dictionary<string, Process>();
|
||||
public ICommand StartCommand { get; set; }
|
||||
public ICommand EditCommand { get; set; }
|
||||
public ICommand WindowLoadedCommand { get; set; }
|
||||
|
||||
public MenuViewModel(IContainerProvider containerProvider)
|
||||
{
|
||||
_dialogService = containerProvider.Resolve<IDialogService>();
|
||||
_regionManager = containerProvider.Resolve<IRegionManager>();
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
EditCommand = new DelegateCommand<string>(OnEdit);
|
||||
StartCommand = new DelegateCommand<string>(OnStart);
|
||||
WindowLoadedCommand = new DelegateCommand(OnWindowLoaded);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void OnWindowLoaded()
|
||||
{
|
||||
if (ConfigList != null) ConfigList.Clear();
|
||||
var JSONFiles = Directory.GetFiles(JsonHelper.SystemPath, "*.json");
|
||||
foreach (var file in JSONFiles)
|
||||
{
|
||||
JsonHelper.ConfigFile = file;
|
||||
var config = JsonHelper.LoadFromFile();
|
||||
if (ConfigList == null)
|
||||
{
|
||||
ConfigList = new ObservableCollection<SystemConfig>();
|
||||
}
|
||||
ConfigList.Add(config);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnStart(string deviceName)
|
||||
{
|
||||
if (ProcessDic.ContainsKey(deviceName))
|
||||
{
|
||||
MessageBox.Show("进程已启动");
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
string currentDir = Environment.CurrentDirectory;
|
||||
string exePath = Path.Combine(currentDir, "BOB.exe");
|
||||
if (!File.Exists(exePath))
|
||||
{
|
||||
MessageBox.Show($"未找到文件: {exePath}");
|
||||
return;
|
||||
}
|
||||
ProcessStartInfo startInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = exePath,
|
||||
Arguments = deviceName,
|
||||
UseShellExecute = true
|
||||
};
|
||||
var configToSave = ConfigList.FirstOrDefault(x => x.Title == deviceName);
|
||||
if (configToSave != null)
|
||||
{
|
||||
JsonHelper.ConfigFile = Path.Combine(JsonHelper.SystemPath, $"{deviceName}.json");
|
||||
JsonHelper.SaveToFile(configToSave);
|
||||
}
|
||||
var process = Process.Start(startInfo);
|
||||
process.EnableRaisingEvents = true;
|
||||
process.Exited += (s, args) =>
|
||||
{
|
||||
ProcessDic.Remove(deviceName);
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
OnWindowLoaded();
|
||||
});
|
||||
};
|
||||
ProcessDic.Add(deviceName, process);
|
||||
string viewName = deviceName switch
|
||||
{
|
||||
"设备1" => "DeviceOne",
|
||||
"设备2" => "DeviceTwo",
|
||||
"设备3" => "DeviceThree",
|
||||
_ => "Other"
|
||||
};
|
||||
var parameters = new NavigationParameters
|
||||
{
|
||||
{ "Title", deviceName },
|
||||
{ "viewName", viewName },
|
||||
};
|
||||
_regionManager.RequestNavigate("MainRegion", viewName, parameters);
|
||||
_eventAggregator.GetEvent<StartProcessEvent>().Publish((deviceName, true));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"启动失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEdit(string deviceName)
|
||||
{
|
||||
if (ProcessDic.ContainsKey(deviceName))
|
||||
{
|
||||
MessageBox.Show("请先关闭进程再进行编辑");
|
||||
return;
|
||||
}
|
||||
JsonHelper.ConfigFile = Path.Combine(JsonHelper.SystemPath, $"{deviceName}.json");
|
||||
var ConfigSystem = JsonHelper.LoadFromFile();
|
||||
var parameters = new DialogParameters
|
||||
{
|
||||
{ "SystemConfig", ConfigSystem },
|
||||
{ "Title", deviceName }
|
||||
};
|
||||
|
||||
_dialogService.ShowDialog("Setting", parameters, r =>
|
||||
{
|
||||
if (r.Result == ButtonResult.OK)
|
||||
{
|
||||
// 用户点击 OK
|
||||
}
|
||||
});
|
||||
}
|
||||
public bool IsNavigationTarget(NavigationContext navigationContext)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnNavigatedFrom(NavigationContext navigationContext)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
_eventAggregator.GetEvent<ChangeCurrentTagEvent>().Publish("Menu");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,9 @@
|
||||
using BOB;
|
||||
using Azure;
|
||||
using BOB;
|
||||
using Common.PubEvent;
|
||||
using MahApps.Metro.Controls;
|
||||
using Prism.Ioc;
|
||||
using ProcessManager.Helpers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
@ -15,111 +19,71 @@ namespace ProcessManager.ViewModels
|
||||
{
|
||||
public class PMainViewModel:BindableBase
|
||||
{
|
||||
private ObservableCollection<SystemConfig> _configList;
|
||||
|
||||
public ObservableCollection<SystemConfig> ConfigList
|
||||
private string _currentTag;
|
||||
public string CurrentTag
|
||||
{
|
||||
get => _configList;
|
||||
set => SetProperty(ref _configList, value);
|
||||
get => _currentTag;
|
||||
set => SetProperty(ref _currentTag, value);
|
||||
}
|
||||
|
||||
private readonly IDialogService _dialogService;
|
||||
private Dictionary<string, Process> ProcessDic { get; set; } = new Dictionary<string, Process>();
|
||||
public ICommand StartCommand { get; set; }
|
||||
public ICommand EditCommand { get; set; }
|
||||
public ICommand WindowLoadedCommand { get; set; }
|
||||
public PMainViewModel(IDialogService dialogService)
|
||||
private IRegionManager _regionManager;
|
||||
private IEventAggregator _eventAggregator;
|
||||
public ICommand MinimizeCommand { get; set; }
|
||||
public ICommand MaximizeCommand { get; set; }
|
||||
public ICommand CloseCommand { get; set; }
|
||||
public ICommand NavigateToMenuCommand { get; set; }
|
||||
public ICommand NavigateToDeviceCommand { get; set; }
|
||||
public PMainViewModel(IContainerProvider containerProvider)
|
||||
{
|
||||
_dialogService = dialogService;
|
||||
EditCommand=new DelegateCommand<string>(OnEdit);
|
||||
StartCommand = new DelegateCommand<string>(OnStart);
|
||||
WindowLoadedCommand = new DelegateCommand(OnWindowLoaded);
|
||||
containerProvider = containerProvider;
|
||||
_eventAggregator=containerProvider.Resolve<IEventAggregator>();
|
||||
_dialogService = containerProvider.Resolve<IDialogService>();
|
||||
_regionManager = containerProvider.Resolve<IRegionManager>();
|
||||
NavigateToMenuCommand = new DelegateCommand(NavigateToMenu);
|
||||
NavigateToDeviceCommand = new DelegateCommand<string>(NavigateToDevice);
|
||||
MinimizeCommand = new DelegateCommand<Window>(MinimizeWindow);
|
||||
MaximizeCommand = new DelegateCommand<Window>(MaximizeWindow);
|
||||
CloseCommand = new DelegateCommand<Window>(CloseWindow);
|
||||
_eventAggregator.GetEvent<ChangeCurrentTagEvent>().Subscribe(ChangeCurrentTag);
|
||||
}
|
||||
|
||||
private void OnWindowLoaded()
|
||||
private void ChangeCurrentTag(string obj)
|
||||
{
|
||||
if (ConfigList != null) ConfigList.Clear();
|
||||
var JSONFiles = Directory.GetFiles(JsonHelper.SystemPath, "*.json");
|
||||
foreach(var file in JSONFiles)
|
||||
{
|
||||
JsonHelper.ConfigFile = file;
|
||||
var config = JsonHelper.LoadFromFile();
|
||||
if(ConfigList==null)
|
||||
{
|
||||
ConfigList = new ObservableCollection<SystemConfig>();
|
||||
}
|
||||
ConfigList.Add(config);
|
||||
}
|
||||
CurrentTag = obj;
|
||||
}
|
||||
|
||||
private void OnStart(string deviceName)
|
||||
private void NavigateToDevice(string page)
|
||||
{
|
||||
if (ProcessDic.ContainsKey(deviceName))
|
||||
{
|
||||
MessageBox.Show("进程已启动");
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
string currentDir = Environment.CurrentDirectory;
|
||||
string exePath = Path.Combine(currentDir, "BOB.exe");
|
||||
if (!File.Exists(exePath))
|
||||
var parameters = new NavigationParameters
|
||||
{
|
||||
MessageBox.Show($"未找到文件: {exePath}");
|
||||
return;
|
||||
}
|
||||
ProcessStartInfo startInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = exePath,
|
||||
Arguments = deviceName,
|
||||
UseShellExecute = true
|
||||
{ "Title", page },
|
||||
};
|
||||
var configToSave = ConfigList.FirstOrDefault(x => x.Title == deviceName);
|
||||
if (configToSave != null)
|
||||
{
|
||||
JsonHelper.ConfigFile = Path.Combine(JsonHelper.SystemPath, $"{deviceName}.json");
|
||||
JsonHelper.SaveToFile(configToSave);
|
||||
}
|
||||
var process = Process.Start(startInfo);
|
||||
process.EnableRaisingEvents = true;
|
||||
process.Exited += (s, args) =>
|
||||
{
|
||||
ProcessDic.Remove(deviceName);
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
OnWindowLoaded();
|
||||
});
|
||||
};
|
||||
ProcessDic.Add(deviceName, process);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"启动失败: {ex.Message}");
|
||||
}
|
||||
_regionManager.RequestNavigate("MainRegion", page,parameters);
|
||||
}
|
||||
|
||||
private void OnEdit(string deviceName)
|
||||
private void NavigateToMenu()
|
||||
{
|
||||
if (ProcessDic.ContainsKey(deviceName))
|
||||
{
|
||||
MessageBox.Show("请先关闭进程再进行编辑");
|
||||
return;
|
||||
}
|
||||
JsonHelper.ConfigFile = Path.Combine(JsonHelper.SystemPath, $"{deviceName}.json");
|
||||
var ConfigSystem = JsonHelper.LoadFromFile();
|
||||
var parameters = new DialogParameters
|
||||
{
|
||||
{ "SystemConfig", ConfigSystem },
|
||||
{ "Title", deviceName }
|
||||
};
|
||||
|
||||
_dialogService.ShowDialog("Setting", parameters, r =>
|
||||
{
|
||||
if (r.Result == ButtonResult.OK)
|
||||
{
|
||||
// 用户点击 OK
|
||||
}
|
||||
});
|
||||
_regionManager.RequestNavigate("MainRegion", "Menu");
|
||||
}
|
||||
private void MinimizeWindow(Window window)
|
||||
{
|
||||
if (window != null)
|
||||
window.WindowState = WindowState.Minimized;
|
||||
}
|
||||
|
||||
private void MaximizeWindow(Window window)
|
||||
{
|
||||
if (window != null)
|
||||
{
|
||||
window.WindowState = window.WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseWindow(Window window)
|
||||
{
|
||||
window?.Close();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
20
ProcessManager/Views/DeviceOther.xaml
Normal file
20
ProcessManager/Views/DeviceOther.xaml
Normal file
@ -0,0 +1,20 @@
|
||||
<UserControl x:Class="ProcessManager.Views.DeviceOther"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:winform="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
|
||||
mc:Ignorable="d">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Loaded">
|
||||
<i:InvokeCommandAction Command="{Binding WindowLoadedCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
<Grid Name="MainGrid">
|
||||
<WindowsFormsHost>
|
||||
<winform:Panel x:Name="PanelHost"></winform:Panel>
|
||||
</WindowsFormsHost>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
29
ProcessManager/Views/DeviceOther.xaml.cs
Normal file
29
ProcessManager/Views/DeviceOther.xaml.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace ProcessManager.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// DeviceOther.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class DeviceOther : UserControl
|
||||
{
|
||||
public System.Windows.Forms.Panel Host => PanelHost;
|
||||
public DeviceOther()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
20
ProcessManager/Views/DeviceThreeView.xaml
Normal file
20
ProcessManager/Views/DeviceThreeView.xaml
Normal file
@ -0,0 +1,20 @@
|
||||
<UserControl x:Class="ProcessManager.DeviceThreeView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:winform="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
|
||||
mc:Ignorable="d">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Loaded">
|
||||
<i:InvokeCommandAction Command="{Binding WindowLoadedCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
<Grid Name="MainGrid">
|
||||
<WindowsFormsHost>
|
||||
<winform:Panel x:Name="PanelHost"></winform:Panel>
|
||||
</WindowsFormsHost>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
29
ProcessManager/Views/DeviceThreeView.xaml.cs
Normal file
29
ProcessManager/Views/DeviceThreeView.xaml.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace ProcessManager
|
||||
{
|
||||
/// <summary>
|
||||
/// DeviceThreeView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class DeviceThreeView : UserControl
|
||||
{
|
||||
public System.Windows.Forms.Panel Host => PanelHost;
|
||||
public DeviceThreeView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
20
ProcessManager/Views/DeviceTwoView.xaml
Normal file
20
ProcessManager/Views/DeviceTwoView.xaml
Normal file
@ -0,0 +1,20 @@
|
||||
<UserControl x:Class="ProcessManager.DeviceTwoView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:winform="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
|
||||
mc:Ignorable="d">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Loaded">
|
||||
<i:InvokeCommandAction Command="{Binding WindowLoadedCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
<Grid Name="MainGrid">
|
||||
<WindowsFormsHost>
|
||||
<winform:Panel x:Name="PanelHost"></winform:Panel>
|
||||
</WindowsFormsHost>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
29
ProcessManager/Views/DeviceTwoView.xaml.cs
Normal file
29
ProcessManager/Views/DeviceTwoView.xaml.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace ProcessManager
|
||||
{
|
||||
/// <summary>
|
||||
/// DeviceTwoView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class DeviceTwoView : UserControl
|
||||
{
|
||||
public System.Windows.Forms.Panel Host => PanelHost;
|
||||
public DeviceTwoView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
20
ProcessManager/Views/DevicesView.xaml
Normal file
20
ProcessManager/Views/DevicesView.xaml
Normal file
@ -0,0 +1,20 @@
|
||||
<UserControl x:Class="ProcessManager.DevicesView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:winform="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
|
||||
mc:Ignorable="d">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Loaded">
|
||||
<i:InvokeCommandAction Command="{Binding WindowLoadedCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
<Grid Name="MainGrid">
|
||||
<WindowsFormsHost>
|
||||
<winform:Panel x:Name="PanelHost"></winform:Panel>
|
||||
</WindowsFormsHost>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
29
ProcessManager/Views/DevicesView.xaml.cs
Normal file
29
ProcessManager/Views/DevicesView.xaml.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace ProcessManager
|
||||
{
|
||||
/// <summary>
|
||||
/// DevicesView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class DevicesView : UserControl
|
||||
{
|
||||
public System.Windows.Forms.Panel Host => PanelHost;
|
||||
public DevicesView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
213
ProcessManager/Views/MainWindow.xaml
Normal file
213
ProcessManager/Views/MainWindow.xaml
Normal file
@ -0,0 +1,213 @@
|
||||
<Window x:Class="ProcessManager.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="hMetroWindowttp://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
|
||||
xmlns:local="clr-namespace:ProcessManager"
|
||||
mc:Ignorable="d"
|
||||
WindowStyle="None"
|
||||
Title="MainWindow" Height="600" Width="1000">
|
||||
<WindowChrome.WindowChrome>
|
||||
<WindowChrome GlassFrameThickness="-1" />
|
||||
</WindowChrome.WindowChrome>
|
||||
|
||||
<materialDesign:DialogHost x:Name="MainDialogHost">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<materialDesign:ColorZone Mode="PrimaryMid"
|
||||
Background="#FF6200EE">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto" />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Menu Grid.Column="0"
|
||||
Background="Transparent"
|
||||
Foreground="White"
|
||||
VerticalAlignment="Center">
|
||||
<MenuItem FontSize="14"
|
||||
Height="50"
|
||||
Header="菜单"
|
||||
Foreground="White"
|
||||
Command="{Binding DataContext.NavigateToMenuCommand, RelativeSource={RelativeSource AncestorType=Window}}">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="Menu"
|
||||
Foreground="White" />
|
||||
</MenuItem.Icon>
|
||||
<MenuItem.Style>
|
||||
<Style TargetType="MenuItem"
|
||||
BasedOn="{StaticResource {x:Type MenuItem}}">
|
||||
<Setter Property="Background"
|
||||
Value="Transparent" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding DataContext.CurrentTag, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
Value="Menu">
|
||||
<Setter Property="Background"
|
||||
Value="#FFBB86FC" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</MenuItem.Style>
|
||||
|
||||
</MenuItem>
|
||||
<MenuItem FontSize="14"
|
||||
Height="50"
|
||||
Header="设备一"
|
||||
Foreground="White"
|
||||
Command="{Binding DataContext.NavigateToDeviceCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="DeviceOne">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="Menu"
|
||||
Foreground="White" />
|
||||
</MenuItem.Icon>
|
||||
<MenuItem.Style>
|
||||
<Style TargetType="MenuItem"
|
||||
BasedOn="{StaticResource {x:Type MenuItem}}">
|
||||
<Setter Property="Background"
|
||||
Value="Transparent" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding DataContext.CurrentTag, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
Value="DeviceOne">
|
||||
<Setter Property="Background"
|
||||
Value="#FFBB86FC" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</MenuItem.Style>
|
||||
</MenuItem>
|
||||
<MenuItem FontSize="14"
|
||||
Height="50"
|
||||
Header="设备二"
|
||||
Foreground="White"
|
||||
Command="{Binding DataContext.NavigateToDeviceCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="DeviceTwo">
|
||||
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="Menu"
|
||||
Foreground="White" />
|
||||
</MenuItem.Icon>
|
||||
<MenuItem.Style>
|
||||
<Style TargetType="MenuItem"
|
||||
BasedOn="{StaticResource {x:Type MenuItem}}">
|
||||
<Setter Property="Background"
|
||||
Value="Transparent" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding DataContext.CurrentTag, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
Value="DeviceTwo">
|
||||
<Setter Property="Background"
|
||||
Value="#FFBB86FC" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</MenuItem.Style>
|
||||
</MenuItem>
|
||||
<MenuItem FontSize="14"
|
||||
Height="50"
|
||||
Header="设备三"
|
||||
Foreground="White"
|
||||
Command="{Binding DataContext.NavigateToDeviceCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="DeviceThree">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="Menu"
|
||||
Foreground="White" />
|
||||
</MenuItem.Icon>
|
||||
<MenuItem.Style>
|
||||
<Style TargetType="MenuItem"
|
||||
BasedOn="{StaticResource {x:Type MenuItem}}">
|
||||
<Setter Property="Background"
|
||||
Value="Transparent" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding DataContext.CurrentTag, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
Value="DeviceThree">
|
||||
<Setter Property="Background"
|
||||
Value="#FFBB86FC" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</MenuItem.Style>
|
||||
</MenuItem>
|
||||
<MenuItem FontSize="14"
|
||||
Height="50"
|
||||
Header="环境箱和水冷机"
|
||||
Foreground="White"
|
||||
Command="{Binding DataContext.NavigateToDeviceCommand, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
CommandParameter="Other">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="Menu"
|
||||
Foreground="White" />
|
||||
</MenuItem.Icon>
|
||||
<MenuItem.Style>
|
||||
<Style TargetType="MenuItem"
|
||||
BasedOn="{StaticResource {x:Type MenuItem}}">
|
||||
<Setter Property="Background"
|
||||
Value="Transparent" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding DataContext.CurrentTag, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
Value="Other">
|
||||
<Setter Property="Background"
|
||||
Value="#FFBB86FC" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</MenuItem.Style>
|
||||
</MenuItem>
|
||||
|
||||
</Menu>
|
||||
|
||||
<Border Grid.Column="1"/>
|
||||
<Menu Grid.Column="2"
|
||||
Margin="0 0 20 0">
|
||||
<MenuItem FontSize="14"
|
||||
Height="50"
|
||||
Header="最小化"
|
||||
Foreground="White"
|
||||
Command="{Binding MinimizeCommand}"
|
||||
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="Minimize"
|
||||
Foreground="White" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem FontSize="14"
|
||||
Height="50"
|
||||
Header="最大化"
|
||||
Foreground="White"
|
||||
Command="{Binding MaximizeCommand}"
|
||||
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="Maximize"
|
||||
Foreground="White" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem FontSize="14"
|
||||
Height="50"
|
||||
Header="关闭"
|
||||
Foreground="White"
|
||||
Command="{Binding CloseCommand}"
|
||||
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="Close"
|
||||
Foreground="White" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</Grid>
|
||||
</materialDesign:ColorZone>
|
||||
|
||||
<ContentControl Grid.Row="1"
|
||||
prism:RegionManager.RegionName="MainRegion"/>
|
||||
</Grid>
|
||||
|
||||
</materialDesign:DialogHost>
|
||||
|
||||
</Window>
|
||||
@ -12,7 +12,7 @@ namespace ProcessManager
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class MainWindow : MetroWindow
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
|
||||
public MainWindow()
|
||||
@ -1,24 +1,23 @@
|
||||
<mah:MetroWindow x:Class="ProcessManager.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="hMetroWindowttp://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
|
||||
xmlns:local="clr-namespace:ProcessManager"
|
||||
mc:Ignorable="d"
|
||||
Title="MainWindow" Height="600" Width="1000">
|
||||
<UserControl x:Class="ProcessManager.MenuView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:ProcessManager"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Loaded">
|
||||
<i:InvokeCommandAction Command="{Binding WindowLoadedCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
|
||||
<materialDesign:DialogHost x:Name="MainDialogHost">
|
||||
<ItemsControl ItemsSource="{Binding ConfigList}">
|
||||
<Grid>
|
||||
<ItemsControl ItemsSource="{Binding ConfigList}"
|
||||
Grid.Row="1">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel IsItemsHost="True"
|
||||
@ -27,7 +26,7 @@
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<materialDesign:Card Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
<materialDesign:Card Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
Width="220"
|
||||
Margin="5"
|
||||
Padding="8"
|
||||
@ -63,11 +62,11 @@
|
||||
<MenuItem Header="编辑"
|
||||
Command="{Binding EditCommand}"
|
||||
CommandParameter="{Binding PlacementTarget.DataContext.Title,
|
||||
RelativeSource={RelativeSource AncestorType=ContextMenu}}" />
|
||||
RelativeSource={RelativeSource AncestorType=ContextMenu}}" />
|
||||
<MenuItem Header="启动"
|
||||
Command="{Binding StartCommand}"
|
||||
CommandParameter="{Binding PlacementTarget.DataContext.Title,
|
||||
RelativeSource={RelativeSource AncestorType=ContextMenu}}" />
|
||||
RelativeSource={RelativeSource AncestorType=ContextMenu}}" />
|
||||
|
||||
</ContextMenu>
|
||||
</materialDesign:Card.ContextMenu>
|
||||
@ -75,5 +74,5 @@
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</materialDesign:DialogHost>
|
||||
</mah:MetroWindow>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
28
ProcessManager/Views/MenuView.xaml.cs
Normal file
28
ProcessManager/Views/MenuView.xaml.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace ProcessManager
|
||||
{
|
||||
/// <summary>
|
||||
/// MenuView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class MenuView : UserControl
|
||||
{
|
||||
public MenuView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
<UserControl x:Class="ProcessManager.Setting"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:local="clr-namespace:ProcessManager"
|
||||
MinHeight="250"
|
||||
93
ProcessManager/WindowEmbedHelper.cs
Normal file
93
ProcessManager/WindowEmbedHelper.cs
Normal file
@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
|
||||
namespace ProcessManager.Helpers
|
||||
{
|
||||
public static class WindowEmbedHelper
|
||||
{
|
||||
private const int GWL_STYLE = -16;
|
||||
private const long WS_CAPTION = 0x00C00000;
|
||||
private const long WS_THICKFRAME = 0x00040000;
|
||||
private const long WS_CHILD = 0x40000000;
|
||||
|
||||
public static void FindAndEmbedWindow(string windowTitle, System.Windows.Forms.Panel panel, int timeoutMs = 10000)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
IntPtr hWnd = IntPtr.Zero;
|
||||
int elapsed = 0;
|
||||
|
||||
while (elapsed < timeoutMs)
|
||||
{
|
||||
hWnd = FindWindow(null, windowTitle);
|
||||
|
||||
if (hWnd != IntPtr.Zero)
|
||||
break;
|
||||
|
||||
await Task.Delay(200);
|
||||
elapsed += 200;
|
||||
}
|
||||
|
||||
if (hWnd == IntPtr.Zero)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
MessageBox.Show($"在 {timeoutMs / 1000.0}s 内未找到窗口:{windowTitle}");
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
EmbedWindow(hWnd, panel);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public static void EmbedWindow(IntPtr childHwnd, System.Windows.Forms.Panel panel)
|
||||
{
|
||||
IntPtr parentHwnd = panel.Handle;
|
||||
|
||||
// 设定父窗口
|
||||
SetParent(childHwnd, parentHwnd);
|
||||
|
||||
// 去掉标题栏
|
||||
long style = GetWindowLong(childHwnd, GWL_STYLE);
|
||||
style &= ~WS_CAPTION;
|
||||
style &= ~WS_THICKFRAME;
|
||||
style |= WS_CHILD;
|
||||
SetWindowLong(childHwnd, GWL_STYLE, style);
|
||||
|
||||
ResizeEmbeddedWindow(childHwnd, panel);
|
||||
|
||||
// 自动resize
|
||||
panel.Resize -= (s, e) => ResizeEmbeddedWindow(childHwnd, panel);
|
||||
panel.Resize += (s, e) => ResizeEmbeddedWindow(childHwnd, panel);
|
||||
}
|
||||
|
||||
public static void ResizeEmbeddedWindow(IntPtr hWnd, System.Windows.Forms.Panel panel)
|
||||
{
|
||||
MoveWindow(hWnd, 0, 0, panel.Width, panel.Height, true);
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr FindWindow(string? lpClassName, string? lpWindowName);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int W, int H, bool repaint);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern long GetWindowLong(IntPtr hWnd, int nIndex);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern long SetWindowLong(IntPtr hWnd, int nIndex, long dwNewLong);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user