目录
如果需要源代码请私信我
lnnovationHubTool 技术与功能说明文档
效果:
一、 引言
本文档详细介绍了 lnnovationHubTool
项目套件的各项功能、核心组件以及具体代码用法。该套件主要由三部分组成:
- UllnnovationHub.ToolKIt: 一个WPF UI组件库,提供丰富的自定义控件和样式。
- lnnovationHubTool.Core: 项目的核心库,提供基础服务如日志管理、参数持久化、通信接口等。
- lnnovationHubTool: 主应用程序,集成核心功能和UI组件,实现具体的业务逻辑。
二、 UllnnovationHub.ToolKIt (UI组件库)
UllnnovationHub.ToolKIt
旨在提供一套美观、易用的WPF UI控件和样式。
2.1 如何使用
编译
UllnnovationHub.ToolKIt
项目,生成UllnnovationHub.ToolKIt.dll
。在您的WPF项目中添加对
UllnnovationHub.ToolKIt.dll
的引用。在
App.xaml
中引入资源字典:<!-- filepath: App.xaml --> <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="pack://application:,,,/UllnnovationHub.ToolKIt;Component/Generic.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources>
在XAML页面中引用命名空间:
xmlns:ui="clr-namespace:UllnnovationHub.ToolKIt.UI;assembly=UllnnovationHub.ToolKIt"
2.2 主要UI控件
2.2.1 UMessageBox
(自定义消息框)
UMessageBox
是一个功能增强的自定义消息框,替代标准的 System.Windows.MessageBox
。
功能特性:
- 支持多种消息类型:
Info
,Error
,Warning
,Question
。 - 支持多种按钮组合:
OK
,OKCancel
,YesNo
,YesNoCancel
。 - 提供同步 (
ShowAndGetResult
) 和异步 (Show
带回调) 的调用方式。 - 可自定义标题和内容。
- 窗口可拖动。
- 自动作为活动窗口的子窗口。
C# 使用方法:
// filepath: ExampleViewModel.cs
using UllnnovationHub.ToolKIt.UI;
using System.Windows; // For MessageBoxResult
using System.Threading.Tasks;
// ...
public void ShowInfoMessage()
{
var messageBox = new UMessageBox();
messageBox.Show("这是一条信息提示。", "提示", UMessageBox.MessageBoxType.Info, UMessageBox.ButtonType.OK, result =>
{
if (result == MessageBoxResult.OK)
{
// 用户点击了确定
System.Diagnostics.Debug.WriteLine("用户点击了确定。");
}
});
}
public void ShowErrorMessageSync()
{
var messageBox = new UMessageBox();
MessageBoxResult result = messageBox.ShowAndGetResult("发生了一个错误。", "错误", UMessageBox.MessageBoxType.Error, UMessageBox.ButtonType.OK);
if (result == MessageBoxResult.OK)
{
// 用户点击了确定
System.Diagnostics.Debug.WriteLine("错误消息框,用户点击了确定。");
}
}
public void ShowQuestionMessage()
{
var messageBox = new UMessageBox();
MessageBoxResult result = messageBox.ShowAndGetResult("您确定要执行此操作吗?", "请确认", UMessageBox.MessageBoxType.Question, UMessageBox.ButtonType.YesNo);
if (result == MessageBoxResult.Yes)
{
// 用户点击了“是”
System.Diagnostics.Debug.WriteLine("问题消息框,用户点击了是。");
}
else if (result == MessageBoxResult.No)
{
// 用户点击了“否”
System.Diagnostics.Debug.WriteLine("问题消息框,用户点击了否。");
}
else if (result == MessageBoxResult.Cancel)
{
// 用户点击了“取消”(如果按钮类型包含取消)
System.Diagnostics.Debug.WriteLine("问题消息框,用户点击了取消。");
}
}
// ...
2.2.2 Card
(卡片控件)
Card
控件用于将内容分组显示在一个具有视觉吸引力的卡片界面中。
XAML 使用方法:
<!-- filepath: YourView.xaml -->
<ui:Card Margin="10" Padding="15">
<StackPanel>
<TextBlock Text="卡片标题" FontSize="16" FontWeight="Bold"/>
<TextBlock Text="这里是卡片的内容区域。"/>
</StackPanel>
</ui:Card>
2.2.3 UTextBox
(增强文本框)
UTextBox
是一个带有附加功能的文本框,例如水印提示 (Placeholder)。其样式定义在 Themes/UTextBox.xaml
中。
XAML 使用方法:
<!-- filepath: YourView.xaml -->
<!-- 假设 UTextBox 通过其 Style 或附加属性支持 Placeholder -->
<TextBox Margin="5" ui:ControlAttach.Placeholder="请输入用户名..." Text="{Binding Username}" Style="{StaticResource UTextBoxBaseStyle}" />
<!-- 或者如果 UTextBox 是一个完全自定义的控件 -->
<!-- <ui:UTextBox Margin="5" Placeholder="请输入用户名..." Text="{Binding Username}" /> -->
注意: ControlAttach.Placeholder
是一个常见的附加属性命名方式,具体请参照 UTextBox.xaml
或相关附加属性类的定义。如果 UTextBox
是一个派生控件,它可能有自己的 Placeholder
属性。
2.2.4 SwitchButton
(开关按钮)
提供一个视觉上类似拨动开关的布尔型输入控件。
XAML 使用方法:
<!-- filepath: YourView.xaml -->
<!-- 假设 SwitchButton 是一个自定义控件 -->
<ui:SwitchButton Margin="5" IsChecked="{Binding IsFeatureEnabled}" />
2.2.5 SwitchRadioButton
(开关单选按钮)
结合了开关和单选按钮的功能,通常用于一组选项中。
XAML 使用方法:
<!-- filepath: YourView.xaml -->
<StackPanel>
<ui:SwitchRadioButton Content="选项 A" GroupName="MyOptionsGroup" IsChecked="{Binding OptionASelected}" />
<ui:SwitchRadioButton Content="选项 B" GroupName="MyOptionsGroup" IsChecked="{Binding OptionBSelected}" />
</StackPanel>
2.2.6 其他控件样式
Generic.xaml
合并了多个资源字典,为WPF原生控件提供了自定义样式。
Button.xaml
: 按钮样式 (e.g.,BaseButtonStyle
,PrimaryButtonStyle
)RadioButton.xaml
: 单选按钮样式TabControl.xaml
: 选项卡控件样式GroupBox.xaml
: 分组框样式 (e.g.,BaseGroupBoxStyle
,SqureShadowHeaderGroupBoxStyle
,RoundedShadowHeaderGroupBoxStyle
)Expander.xaml
: 折叠面板样式ComboBox.xaml
: 下拉框样式PasswordBox.xaml
: 密码框样式CheckBox.xaml
: 复选框样式ListBox.xaml
: 列表框样式TreeView.xaml
&TreeViewItem.xaml
: 树视图样式MenuItem.xaml
: 菜单项样式ImageButton.xaml
: 图像按钮样式Slider.xaml
: 滑动条样式ListView.xaml
: 列表视图样式DataGrid.xaml
: 数据网格样式HorizontolSeparator.xaml
&VerticalSeparator.xaml
: 分隔线样式
XAML 使用方法 (应用样式):
<!-- filepath: YourView.xaml -->
<Button Content="默认样式按钮" Margin="5" />
<Button Content="主按钮样式" Margin="5" Style="{StaticResource PrimaryButton}" /> <!-- 假设样式Key为 PrimaryButton -->
<GroupBox Header="测试基础样式" Margin="10" Style="{StaticResource BaseGroupBoxStyle}"/>
<GroupBox Header="方形阴影标题" Margin="10" Style="{StaticResource SqureShadowHeaderGroupBoxStyle}"/>
<GroupBox Header="圆形阴影标题" Margin="10" Style="{StaticResource RoundedShadowHeaderGroupBoxStyle}"/>
<DataGrid Margin="5" Style="{StaticResource DataGridStyle1}"> <!-- 假设样式Key为 DataGridStyle1 -->
<!-- Columns and ItemsSource -->
</DataGrid>
注意: 具体的样式键名 (Style Key) 取决于各个 Themes/*.xaml
文件中的定义。
2.3 Helper
类
2.3.1 UllnnovationHub.ToolKIt.Helper.MessageBox
这是一个静态辅助类,封装了对 UMessageBox
的调用,简化了消息框的显示。
C# 使用方法:
// filepath: ExampleViewModel.cs
using MessageBox = UllnnovationHub.ToolKIt.Helper.MessageBox; // 为方便使用设置别名
using System.Windows; // For MessageBoxResult
// ...
public void ShowSimplifiedInfo()
{
// 假设 Helper.MessageBox 内部会创建和配置 UMessageBox 实例
MessageBox.Info("操作已成功完成。", "成功");
}
public void ShowSimplifiedError()
{
MessageBox.Error("保存配置时发生错误。", "错误");
}
public void ShowSimplifiedWarning()
{
MessageBox.Warning("这是一个警告信息。", "警告");
}
public MessageBoxResult ShowSimplifiedConfirm()
{
// 假设 Confirm 方法返回 MessageBoxResult
return MessageBox.Confirm("您确定要删除这条记录吗?", "请确认");
}
// 示例:如果 Helper.MessageBox 提供了直接返回 UMessageBox.MessageBoxType 的方法
public void ShowMessageWithSpecificType()
{
// 假设 Show 方法签名类似:
// static void Show(string message, string caption, UMessageBox.MessageBoxType type, UMessageBox.ButtonType buttonType)
// MessageBox.Show("这是一条询问消息", "询问", UMessageBox.MessageBoxType.Question, UMessageBox.ButtonType.YesNoCancel);
}
// ...
三、 lnnovationHubTool.Core (核心库)
lnnovationHubTool.Core
提供了应用程序的基础服务和核心逻辑。
3.1 日志管理 (IW.Core.Log
)
3.1.1 LogManage
静态类,提供全局的日志记录功能。
功能特性:
- 异步日志记录,避免阻塞主线程。
- 支持多种日志级别:
Info
,Procedure
,Warn
,Error
。 - 可自定义日志文件路径 (
CustomLogPath
) 和文件名 (CustomLogFileName
)。 - 可自定义日志格式 (
LogFormatter
)。 - 自动清理旧日志文件 (可配置
SaveDays
)。 - 提供日志读取功能 (
Read
)。 - 日志写入事件回调 (
OnWriteLog
),用于实时显示日志。 - 可关联用户管理服务 (
IUserManageService
) 以记录操作员信息。
C# 初始化与配置:
// filepath: App.xaml.cs or a Bootstrapper class
using IW.Core.Log;
using IW.Core.CommonTool; // For PathHelper
using IW.Core.Services.UserRoleConfigure.Services; // For IUserManageService (假设接口路径)
using System;
using System.IO;
using System.Windows; // For Application
public partial class App : Application
{
private IUserManageService _userManageService; // 示例:用户服务实例
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
// 示例:初始化用户服务 (具体实现依赖于您的项目)
// _userManageService = new YourUserManageServiceImplementation();
// LogManage.SetUserManageService(_userManageService);
LogManage.Init(); // 应用默认配置和自定义格式化器
// 可选:在Init之后覆盖或补充配置
LogManage.CustomLogPath = () => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ApplicationLogs");
LogManage.CustomLogFileName = () => $"AppLog_{DateTime.Now:yyyy-MM-dd}.log";
LogManage.SaveDays = 60; // 保留60天日志
// 示例:订阅日志写入事件 (LogManage.Init 中可能已有默认的控制台输出)
LogManage.OnWriteLog += (logItem) =>
{
// 在UI上显示日志,注意线程调度
Application.Current?.Dispatcher?.Invoke(() => {
// 例如:添加到ObservableCollection<LogItem> 以更新UI
// LogViewModel.LogEntries.Add(logItem);
});
System.Diagnostics.Debug.WriteLine($"实时日志回调: [{logItem.Level}] {logItem.Message}");
};
}
protected override void OnExit(ExitEventArgs e)
{
LogManage.Close(5); // 程序退出前关闭日志,等待最多5秒完成写入
base.OnExit(e);
}
}
C# 日志记录方法:
// filepath: ExampleService.cs
using IW.Core.Log;
using System;
public class ExampleService
{
public void PerformDatabaseOperation(string connectionString)
{
LogManage.Info("数据库操作开始。");
try
{
LogManage.Procedure($"尝试连接到数据库: {connectionString}");
// ... 执行数据库操作 ...
if (string.IsNullOrEmpty(connectionString))
{
LogManage.Warn("连接字符串为空,操作可能失败。");
}
// 模拟操作
System.Threading.Thread.Sleep(100);
LogManage.Procedure("数据库操作步骤1完成。");
LogManage.Info("数据库操作成功完成。");
}
catch (TimeoutException tex)
{
LogManage.Error("数据库操作超时。", tex);
}
catch (Exception ex)
{
LogManage.Error($"数据库操作发生未知错误: {ex.Message}", ex);
}
}
}
C# 日志读取方法:
// filepath: LogViewModel.cs
using IW.Core.Log;
using System;
using System.Collections.Generic;
using System.Linq;
// using System.Collections.ObjectModel; // For ObservableCollection if binding to UI
public class LogViewModel // : YourViewModelBaseClass
{
// public ObservableCollection<LogItem> DisplayedLogs { get; } = new ObservableCollection<LogItem>();
public void LoadLogsForToday(LogLevel logLevelFilter)
{
DateTime startTime = DateTime.Today;
DateTime endTime = DateTime.Now; // 或者 DateTime.Today.AddDays(1).AddTicks(-1) 表示到今天结束
List<LogItem> logs = LogManage.Read(startTime, endTime, logLevelFilter);
// DisplayedLogs.Clear();
if (logs != null)
{
// foreach (var log in logs)
// {
// DisplayedLogs.Add(log);
// }
}
}
}
3.1.2 LogItem
表示单条日志记录的数据结构。
主要属性:
Time
:string
(在LogManage.Read
中解析为DateTime
前的原始字符串) - 日志记录时间。Level
:string
- 日志级别 (如 “Info”, “Error”)。ThreadId
:string
- 记录日志的线程ID。UserName
:string
- 操作用户名。UserRole
:string
- 操作用户角色。Message
:string
- 日志消息内容。
3.1.3 LogLevel
(枚举)
定义日志的严重级别,用于记录和筛选。
Info
: 普通信息。Warn
: 警告信息。Error
: 错误信息。Procedure
: 流程/调试信息 (在LogManage.Debug
方法中被映射为LogLevel.Procedure
进行记录)。All
: 用于LogManage.Read
时,表示读取所有级别的日志。
3.2 公共工具 (IW.Core.CommonTool
)
3.2.1 PathHelper
静态类,用于管理应用程序中常用的路径。
主要属性 (示例):
G_LogPath
:string
- 日志文件的存储路径。由LogManage.CustomLogPath
委托确定,PathHelper
可能提供默认值或被LogManage
使用。G_Parameters
:string
- 参数文件的存储路径 (基于功能说明.md
推断)。
C# 使用方法:
// filepath: ConfigurationService.cs
using IW.Core.CommonTool; // Assuming PathHelper is here
using System.IO;
public class ConfigurationService
{
public string GetParameterFilePath(string fileName)
{
// 假设 PathHelper.G_Parameters 提供了参数文件夹的根路径
// string parametersDirectory = PathHelper.G_Parameters;
// if (!Directory.Exists(parametersDirectory))
// {
// Directory.CreateDirectory(parametersDirectory);
// }
// return Path.Combine(parametersDirectory, fileName);
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Parameters", fileName); // Fallback example
}
public string GetLogDirectory()
{
return PathHelper.G_LogPath; // G_LogPath is set by LogManage.CustomLogPath
}
}
3.3 用户角色管理 (IW.Core.Services.UserRoleConfigure.Services
)
3.3.1 IUserManageService
接口,定义用户登录、权限检查等用户管理相关操作。LogManage
通过 SetUserManageService
方法接收此接口的实例,以在日志中记录当前用户信息。
接口方法示例 (概念性):
// filepath: IUserManageService.cs (Conceptual)
// namespace IW.Core.Services.UserRoleConfigure.Services;
// public interface IUserManageService
// {
// CurrentUser CurrentUser { get; } // Represents the logged-in user's details
// bool Login(string username, string password);
// void Logout();
// bool HasPermission(string permissionKey);
// }
// public class CurrentUser
// {
// public string UserName { get; set; }
// public string Role { get; set; } // Or an enum for roles
// }
在 LogManage
中的使用:
LogManage
内部在格式化日志时,如果 _userManageService
实例不为空,会尝试调用 _userManageService.CurrentUser
来获取用户名和角色。
3.4 参数服务
3.4.1 IParameterService
(接口)
定义参数持久化(保存和加载)的方法,通常使用XML或JSON序列化。
接口定义 (推断自 功能说明.md
):
// filepath: IParameterService.cs (Conceptual, likely in IW.Core.Services namespace)
public interface IParameterService
{
void SaveParameter<T>(T parameter, string fileName) where T : class;
T LoadParameter<T>(string fileName) where T : class, new();
}
C# 使用方法 (假设已实现并注入 _parameterService
):
// filepath: SettingsViewModel.cs
// using IW.Core.Services; // For IParameterService
// public class AppSettings { /* ... properties ... */ }
// private IParameterService _parameterService;
// public AppSettings CurrentSettings { get; set; }
public void LoadApplicationSettings()
{
// CurrentSettings = _parameterService.LoadParameter<AppSettings>("ApplicationSettings.xml");
// if (CurrentSettings == null)
// {
// CurrentSettings = new AppSettings(); // Load defaults or create new
// }
}
public void SaveApplicationSettings()
{
// if (CurrentSettings != null)
// {
// _parameterService.SaveParameter(CurrentSettings, "ApplicationSettings.xml");
// }
}
3.4.2 StringWrapper
用于序列化单个字符串值,当需要将字符串作为独立的XML文件内容或者需要一个对象根进行序列化时使用。
类定义 ():
// filepath: StringWrapper.cs (Conceptual, likely in IW.Core.Models or Common namespace)
using System;
[Serializable]
public class StringWrapper
{
public string Value { get; set; }
public StringWrapper() { Value = string.Empty; }
public StringWrapper(string value) { Value = value; }
public static implicit operator string(StringWrapper wrapper) => wrapper?.Value;
public static implicit operator StringWrapper(string value) => new StringWrapper(value);
}
C# 使用方法:
// filepath: DeviceConfigurationService.cs
// using IW.Core.Services; // For IParameterService
// using IW.Core.Models; // For StringWrapper
// private IParameterService _parameterService;
public void SaveDeviceIdentifier(string deviceId)
{
// StringWrapper wrapper = deviceId; // Implicit conversion from string
// _parameterService.SaveParameter(wrapper, "DeviceIdentifier.xml");
}
public string LoadDeviceIdentifier()
{
// StringWrapper wrapper = _parameterService.LoadParameter<StringWrapper>("DeviceIdentifier.xml");
// string deviceId = wrapper; // Implicit conversion to string
// return deviceId ?? "DefaultDeviceID";
return "DefaultDeviceID_Placeholder"; // Placeholder
}
3.5 通信功能 ()
3.5.1 Modbus通信 (ModbusTCP
)
用于与支持Modbus TCP协议的设备(如PLC)通信。
C# 使用方法 (概念性, 基于 功能说明.md
):
// filepath: ModbusDeviceService.cs
// Assuming a ModbusTCP class exists, e.g., from a third-party library or custom implementation
// Example: using EasyModbus; // If using EasyModbusTCP .NET package
public class ModbusDeviceService
{
// private ModbusClient _modbusClient; // Example using EasyModbus
public ModbusDeviceService(string ipAddress, int port)
{
// _modbusClient = new ModbusClient(ipAddress, port);
}
public bool Connect()
{
// try
// {
// _modbusClient.Connect();
// return _modbusClient.Connected;
// }
// catch (Exception ex)
// {
// LogManage.Error("Modbus连接失败", ex);
// return false;
// }
return false; // Placeholder
}
public int[] ReadHoldingRegisters(int startAddress, int quantity)
{
// if (!_modbusClient.Connected) return null;
// try
// {
// return _modbusClient.ReadHoldingRegisters(startAddress, quantity);
// }
// catch (Exception ex)
// {
// LogManage.Error($"读取Modbus保持寄存器失败 (地址:{startAddress},数量:{quantity})", ex);
// return null;
// }
return null; // Placeholder
}
public bool WriteSingleRegister(int address, int value)
{
// if (!_modbusClient.Connected) return false;
// try
// {
// _modbusClient.WriteSingleRegister(address, value);
// return true;
// }
// catch (Exception ex)
// {
// LogManage.Error($"写入Modbus单个寄存器失败 (地址:{address},值:{value})", ex);
// return false;
// }
return false; // Placeholder
}
public void Disconnect()
{
// _modbusClient?.Disconnect();
}
}
3.5.2 TCP/IP 通信 ()
通用的TCP客户端通信实现。
C# 使用方法 (概念性, 基于 功能说明.md
):
// filepath: GenericTcpDeviceService.cs
// Assuming TCPCommunicate class exists
// public class GenericTcpDeviceService
// {
// private TCPCommunicate _tcpComm;
// public event EventHandler<byte[]> DataReceived;
// public GenericTcpDeviceService(string ipAddress, int port)
// {
// _tcpComm = new TCPCommunicate(ipAddress, port);
// _tcpComm.DataReceivedEvent += OnRawDataReceived;
// }
// private void OnRawDataReceived(object sender, byte[] data)
// {
// DataReceived?.Invoke(this, data); // Forward the event
// string receivedString = System.Text.Encoding.UTF8.GetString(data);
// LogManage.Procedure($"TCP收到数据: {receivedString}");
// }
// public bool OpenConnection()
// {
// try
// {
// _tcpComm.Open();
// return true; // Assuming Open() throws on failure or returns status
// }
// catch (Exception ex)
// {
// LogManage.Error("TCP连接打开失败", ex);
// return false;
// }
// }
// public bool SendMessage(string message)
// {
// try
// {
// _tcpComm.SendMessage(message);
// return true;
// }
// catch (Exception ex)
// {
// LogManage.Error("TCP发送消息失败", ex);
// return false;
// }
// }
// public void CloseConnection()
// {
// _tcpComm?.Close();
// }
// }
3.5.3 串口通信 ()
用于与通过串口连接的设备通信。
C# 使用方法 (概念性, 基于 功能说明.md
):
// filepath: PowerSupplyService.cs
// Assuming SerialPortData, PowerManager, and an ICommunication (or similar) serial port class exist
// public enum PowerChannel { Power1, Power2 } // Example enum
// public class PowerSupplyService
// {
// private PowerManager _powerManager; // Manages power supply communication instances
// public PowerSupplyService()
// {
// _powerManager = new PowerManager(); // Initialize PowerManager
// }
// public bool ConfigureSerialPort(PowerChannel channel, SerialPortData portConfig)
// {
// // _powerManager.Setting(portConfig, channel); // Configures the serial port for the given channel
// // ICommunication serialComm = channel == PowerChannel.Power1 ? _powerManager.powerComunication1 : _powerManager.powerComunication2;
// // try
// // {
// // serialComm?.Open();
// // return serialComm?.IsOpen ?? false;
// // }
// // catch (Exception ex)
// // {
// // LogManage.Error($"配置并打开串口 {portConfig.PortName} 失败 (通道: {channel})", ex);
// // return false;
// // }
// return false; // Placeholder
// }
// public bool SendSerialCommand(PowerChannel channel, string command)
// {
// // ICommunication serialComm = channel == PowerChannel.Power1 ? _powerManager.powerComunication1 : _powerManager.powerComunication2;
// // if (serialComm == null || !serialComm.IsOpen)
// // {
// // LogManage.Warn($"串口未打开或未配置 (通道: {channel}),无法发送命令: {command}");
// // return false;
// // }
// // try
// // {
// // serialComm.SendMessage(command);
// // return true;
// // }
// // catch (Exception ex)
// // {
// // LogManage.Error($"通过串口发送命令失败 (通道: {channel}, 命令: {command})", ex);
// // return false;
// // }
// return false; // Placeholder
// }
// }
3.6 TaskManager
流程管理器 ()
用于管理和执行定义好的工艺流程或任务序列。
功能特性:
- 初始化工作站列表 (
IniStationList
)。 - 控制流程的初始化 (
Init
)、自动运行 (AutoRun
)、暂停 (Pause
)、继续 (Continue
)、停止 (Stop
)。 - 通过
OnStationStatusChange
事件回调监控工作站状态变化。
C# 使用方法 (概念性, 基于 功能说明.md
):
// filepath: ProductionControlViewModel.cs
// Assuming TaskManager is a singleton or static accessible class
// using System.Collections.ObjectModel; // For UI binding
// using System.Linq;
// using System.Windows; // For Application.Current.Dispatcher
// public class StationUIModel { public string Id { get; set; } public string Status { get; set; } public string Message { get; set; } }
// public class ProductionControlViewModel // : YourViewModelBase
// {
// // public ObservableCollection<StationUIModel> Stations { get; } = new ObservableCollection<StationUIModel>();
// public ProductionControlViewModel()
// {
// // TaskManager.Instance.OnStationStatusChange += OnStationStatusChanged;
// }
// public void InitializeWorkflow(string deviceType)
// {
// // TaskManager.IniStationList(deviceType); // Initializes stations based on device type
// // TaskManager.Instance.Init(); // Initializes the overall task manager/workflow
// // PopulateStationsFromTaskManager(); // Helper to initially populate UI
// }
// private void OnStationStatusChanged(StationData station) // Assuming StationData is the type from TaskManager
// {
// // Application.Current.Dispatcher.Invoke(() =>
// // {
// // var uiStation = Stations.FirstOrDefault(s => s.Id == station.Id);
// // if (uiStation != null)
// // {
// // uiStation.Status = station.Status;
// // uiStation.Message = station.Message;
// // }
// // else
// // {
// // // Stations.Add(new StationUIModel { Id = station.Id, Status = station.Status, Message = station.Message });
// // }
// // });
// }
// public void StartAutoMode() => TaskManager.Instance.AutoRun();
// public void PauseAutoMode() => TaskManager.Instance.Pause();
// public void ContinueAutoMode() => TaskManager.Instance.Continue();
// public void StopAutoMode() => TaskManager.Instance.Stop();
// // private void PopulateStationsFromTaskManager() { /* ... */ }
// }
四、 lnnovationHubTool (主应用程序)
主应用程序集成了 UllnnovationHub.ToolKIt
和 lnnovationHubTool.Core
,并使用 Prism 框架构建模块化的WPF应用。
4.1 主要视图 (Views)
MainView
: 应用程序的主窗口或主内容区域,通常包含导航和内容区域。LogView
: 显示系统日志,提供筛选和查看功能。AlarmView
: 显示系统报警信息。UserManageView
: 用户管理界面 (推断)。SettingView
: 系统设置界面。CameraView
: 相机图像显示和控制界面。DeBugView
: 包含各种调试工具和相机调试功能的视图。ParameterView
: 参数配置界面。- CustomControls Views (
AxisSettingView
,DebugCameraView
,RecipeView
): 特定功能的自定义控件或组合视图,用于更复杂的交互。
4.2 Prism 框架集成
4.2.1 模块注册 (Bootstrapper or App class)
Prism应用通常有一个引导程序(Bootstrapper)或在 App.xaml.cs
中配置模块。
// filepath: App.xaml.cs or YourBootstrapper.cs
// using Prism.DryIoc; // Or Prism.Unity, Prism.Ninject etc.
// using Prism.Ioc;
// using Prism.Modularity;
// using System.Windows;
// using YourMainModule; // Namespace of your module
// public class YourBootstrapper : PrismBootstrapper
// {
// protected override DependencyObject CreateShell()
// {
// return Container.Resolve<ShellWindow>(); // Your main window
// }
// protected override void RegisterTypes(IContainerRegistry containerRegistry)
// {
// // Register global services, etc.
// }
// protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
// {
// moduleCatalog.AddModule<MainModule>(); // Example: Main application module
// moduleCatalog.AddModule<LoggingModule.LoggingModule>(); // Example: A dedicated logging module
// // ... other modules
// }
// }
4.2.2 视图注册与导航
视图和视图模型在模块中注册,并通过区域管理器 (RegionManager) 进行导航。
// filepath: MainModule.cs (Example Prism Module)
// using Prism.Ioc;
// using Prism.Modularity;
// using Prism.Regions;
// using YourApp.Views; // Namespace for views
// using YourApp.ViewModels; // Namespace for viewmodels
// public class MainModule : IModule
// {
// public void OnInitialized(IContainerProvider containerProvider)
// {
// var regionManager = containerProvider.Resolve<IRegionManager>();
// // Initial navigation if needed
// regionManager.RequestNavigate("ContentRegionNameInShell", nameof(MainView));
// }
// public void RegisterTypes(IContainerRegistry containerRegistry)
// {
// // Register views for navigation
// containerRegistry.RegisterForNavigation<MainView, MainViewModel>();
// containerRegistry.RegisterForNavigation<LogView, LogViewModel>();
// containerRegistry.RegisterForNavigation<AlarmView, AlarmViewModel>();
// // ... register other views and their viewmodels
// }
// }
在 ViewModel 中导航:
// filepath: ShellViewModel.cs or AnyViewModelWithNavigation.cs
// using Prism.Commands;
// using Prism.Mvvm;
// using Prism.Regions;
// public class ShellViewModel : BindableBase
// {
// private readonly IRegionManager _regionManager;
// public DelegateCommand<string> NavigateCommand { get; private set; }
// public ShellViewModel(IRegionManager regionManager)
// {
// _regionManager = regionManager;
// NavigateCommand = new DelegateCommand<string>(Navigate);
// }
// private void Navigate(string navigationPath)
// {
// // navigationPath would be the name of the view registered for navigation, e.g., "LogView"
// _regionManager.RequestNavigate("ContentRegionNameInShell", navigationPath, navigationResult =>
// {
// if (navigationResult.Result == false)
// {
// LogManage.Error($"导航到 {navigationPath} 失败: {navigationResult.Error?.Message}");
// }
// });
// }
// }
4.3 相机集成 (DeBugView
相关)
系统支持多种品牌相机(海康、Basler、大恒),通过工厂模式创建相机实例。
4.3.1 ICamera
(接口) 和 CamFactory
ICamera
: 定义相机操作的通用接口 (如初始化、枚举设备、打开/关闭设备、开始/停止抓图、获取/设置参数、注册图像回调)。CamFactory
: 工厂类,用于根据品牌 (CameraBrand
枚举) 创建具体的相机实例。CameraBrand
(枚举):HIK
,Basler
,DaHeng
。
C# 使用方法 ():
// filepath: CameraControlService.cs or DebugCameraViewModel.cs
// using IW.Camera; // Assuming camera related classes are in this namespace (ICamera, CamFactory, CameraBrand, ImageEventArgs)
// using System.Collections.Generic;
// using System.Linq;
// using System.Windows.Media.Imaging; // For BitmapSource if image is converted
// public class CameraControlService
// {
// private ICamera _activeCamera;
// public event EventHandler<BitmapSource> NewImageReceived; // Example event for UI
// public List<string> EnumerateDevices(CameraBrand brand)
// {
// // This might be a static method on CamFactory or require a temporary instance
// // return CamFactory.GetDeviceEnum(brand);
// // Or, if GetListEnum is instance-based after CreatCamera:
// ICamera tempCam = CamFactory.CreatCamera(brand);
// return tempCam?.GetListEnum(); // Ensure to handle tempCam disposal if it opens resources
// }
// public bool InitializeCamera(CameraBrand brand, string deviceIdentifier) // deviceIdentifier could be SN or UserDefinedName
// {
// if (_activeCamera != null && _activeCamera.IsDeviceOpen())
// {
// _activeCamera.CloseDevice();
// _activeCamera.ImageGrabbed -= OnCameraImageGrabbed; // Unsubscribe
// }
// _activeCamera = CamFactory.CreatCamera(brand);
// if (_activeCamera == null)
// {
// LogManage.Error($"创建相机实例失败: {brand}");
// return false;
// }
// if (!_activeCamera.InitDevice(deviceIdentifier)) // InitDevice might take SN or index
// {
// LogManage.Error($"初始化相机设备失败: {deviceIdentifier} ({brand})");
// return false;
// }
// _activeCamera.ImageGrabbed += OnCameraImageGrabbed; // Subscribe to image event
// LogManage.Info($"相机 {deviceIdentifier} ({brand}) 初始化成功。");
// return true;
// }
// public void StartGrabbing()
// {
// _activeCamera?.StartGrabbing();
// }
// public void StopGrabbing()
// {
// _activeCamera?.StopGrabbing();
// }
// public void CloseCamera()
// {
// if (_activeCamera != null)
// {
// _activeCamera.StopGrabbing(); // Ensure grabbing is stopped
// _activeCamera.CloseDevice(); // This should handle unregistering/releasing resources
// _activeCamera.ImageGrabbed -= OnCameraImageGrabbed;
// _activeCamera = null;
// LogManage.Info("相机已关闭。");
// }
// }
// private void OnCameraImageGrabbed(object sender, ImageEventArgs e) // Assuming ImageEventArgs contains image data
// {
// // Process e.Bitmap or e.RawImageData
// // Example: Convert to BitmapSource for WPF UI
// // BitmapSource bmpSource = ConvertToBitmapSource(e.Bitmap);
// // NewImageReceived?.Invoke(this, bmpSource);
// }
// // public BitmapSource ConvertToBitmapSource(System.Drawing.Bitmap bitmap) { /* ... conversion logic ... */ return null; }
// }
心跳机制:
为解决调试时直接中断程序导致相机未注销的问题,网口相机增加了心跳检测。若连接断开超过预设时间(如1000ms),相机会自动注销,方便下次直接连接。此功能通常在相机SDK的特定实现中处理,或由 ICamera
实现类内部管理。
>如果需要源代码请私信我