上节已经对本软件的功能和意图进行了详细讲解,这节就不再啰嗦,本节主要对功能实现和代码部分展开讲解.
01
—
前台代码
前台XAML:
<Windowx:Class="EquipmentMonitor.EquipmentView"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:EquipmentMonitor"xmlns:cal="http://www.caliburnproject.org"mc:Ignorable="d"WindowStartupLocation="CenterScreen"Title="EquipmentMonitor"Height="610"Width="500"Icon="Display.png"><Window.Resources><StyleTargetType="Label"><SetterProperty="HorizontalAlignment"Value ="Center"/><SetterProperty="VerticalAlignment"Value ="Center"/><SetterProperty="FontSize"Value ="14"/><SetterProperty="FontWeight"Value ="Black"/></Style><StyleTargetType="ListBox"><SetterProperty="HorizontalAlignment"Value ="Left"/><SetterProperty="VerticalAlignment"Value ="Top"/><SetterProperty="FontSize"Value ="14"/><SetterProperty="FontWeight"Value ="Black"/><SetterProperty="ItemTemplate"><Setter.Value><DataTemplate><BorderBorderBrush="Gray"BorderThickness="2"Margin="2" ><StackPanelOrientation="Vertical"Background="{Binding BackBrush}"cal:Message.Attach="[Event MouseLeftButtonUp]=[BuildClick($source,$eventArgs)]"><ImageSource="../Image/Display.png"Width="100"Height="100" /><LabelContent="{Binding Title}" /></StackPanel></Border></DataTemplate></Setter.Value></Setter><SetterProperty="ItemsPanel"><Setter.Value><ItemsPanelTemplate><WrapPanelOrientation="Horizontal" /></ItemsPanelTemplate></Setter.Value></Setter></Style></Window.Resources><Grid><ListBoxx:Name="EqplistBox"ItemsSource="{Binding FileDTOList}"ScrollViewer.HorizontalScrollBarVisibility="Disabled"Margin="2"/></Grid></Window>
前台代码异常简单,主要就是一个ListBox ,然后通过设置模板,将图片和标签进行界面显示
02
—
后台代码
① 数据模型:FileDTO.cs
using PropertyChanged;using System;using System.Collections.ObjectModel;using System.Text;using System.Windows.Media;namespaceEquipmentMonitor.Model{ [AddINotifyPropertyChangedInterface]publicclassFileDTO {publicFileDTO() { BackBrushList = new ObservableCollection<Brush>(); BackBrushList.Add(Brushes.White); BackBrush = Brushes.White; CurrentTime = DateTime.Now; }publicstring Title { get; set; }publicstring MonitorPath { get; set; }publicint TimeSpan { get; set; }public DateTime CurrentTime { get; set; }public Brush BackBrush { get; set; }public ObservableCollection<Brush> BackBrushList { get; set; }publicoverridestringToString() { StringBuilder report = new StringBuilder(); report.AppendLine($"[Title] = [{Title}]"); report.AppendLine($"[MonitorPath] = [{MonitorPath}]"); report.AppendLine($"[TimeSpan] = [{TimeSpan}]"); report.AppendLine($"[CurrentTime] = [{CurrentTime}]"); report.AppendLine($"[BackBrush] = [{BackBrush}]");foreach (var item in BackBrushList) { report.AppendLine($"[BackBrush] = [{item}]"); }return report.ToString(); } }}
这里重写了tostring方法,主要是为了方便log打印.
[AddINotifyPropertyChangedInterface]是PropertyChanged.dll下面的方法,在类顶部附加后,属性变更就可以自动通知界面,而不用一个一个去触发.
② 帮助类:
AutoStartHelper.cs
using Microsoft.Win32;using System;using System.Windows.Forms;namespaceEquipmentMonitor.Helper{publicclassAutoStartHelper {publicstaticvoidAutoStart(bool isAuto = true, bool showinfo = true) {try {if (isAuto == true) { RegistryKey R_local = Registry.CurrentUser;//RegistryKey R_local = Registry.CurrentUser; RegistryKey R_run = R_local.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run"); R_run.SetValue("应用名称", Application.ExecutablePath); R_run.Close(); R_local.Close(); }else { RegistryKey R_local = Registry.CurrentUser;//RegistryKey R_local = Registry.CurrentUser; RegistryKey R_run = R_local.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run"); R_run.DeleteValue("应用名称", false); R_run.Close(); R_local.Close(); } }//if (showinfo)// MessageBox.Show("您需要管理员权限修改", "提示");// Console.WriteLine("您需要管理员权限修改");catch (Exception ex) {string content = DateTime.Now.ToLocalTime() + " 0001_" + "您需要管理员权限修改" + "\n" + ex.StackTrace + "\r\n"; LogHelper.logWrite(content); } } }}
没啥好讲的,就是为了软件第一次打开后,把启动信息添加到注册表,下次开机后软件可以自己启动;
LogHelper.cs:这是一个简易的log打印帮助类
using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Text;using System.Threading.Tasks;namespaceEquipmentMonitor.Helper{publicclassLogHelper {publicstaticvoidlogWrite(string Message, string StackTrace = null) {if (!File.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\log.txt")) { File.Create(AppDomain.CurrentDomain.BaseDirectory + "\\log.txt").Close(); }string fileName = AppDomain.CurrentDomain.BaseDirectory + "\\log.txt";string content = DateTime.Now.ToLocalTime() + Message + "\n" + StackTrace + "\r\n"; StreamWriter sw = new StreamWriter(fileName, true); sw.Write(content); sw.Close(); sw.Dispose(); } }}
XMLHelper.cs:配置文件读取帮助类
using EquipmentMonitor.Model;using System;using System.Collections.ObjectModel;using System.Xml;namespaceEquipmentMonitor.Helper{publicclassXMLHelper {public ObservableCollection<FileDTO> XmlDocReader() {try {//XmlDocument读取xml文件 XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(AppDomain.CurrentDomain.BaseDirectory + "\\config.xml");//获取xml根节点 XmlNode xmlRoot = xmlDoc.DocumentElement;if (xmlRoot == null) { LogHelper.logWrite("xmlRoot is null");returnnull; } ObservableCollection<FileDTO> FileDTOList = new ObservableCollection<FileDTO>();//读取所有的节点foreach (XmlNode node in xmlRoot.SelectNodes("FilePath")) { FileDTOList.Add(new FileDTO { Title = node.SelectSingleNode("Title").InnerText, MonitorPath = node.SelectSingleNode("MonitorPath").InnerText, TimeSpan = int.Parse(node.SelectSingleNode("TimeSpan").InnerText) }); }return FileDTOList; }catch (Exception ex) { LogHelper.logWrite(ex.Message, ex.StackTrace);returnnull; } } }}
③ Viewmodel部分:EquipmentViewModel.cs
using Caliburn.Micro;using EquipmentMonitor.Helper;using EquipmentMonitor.Model;using PropertyChanged;using System;using System.Collections.ObjectModel;using System.IO;using System.Threading;using System.Threading.Tasks;using System.Windows;using System.Windows.Controls;using System.Windows.Input;using System.Windows.Media;using System.Windows.Threading;namespaceEquipmentMonitor{ [AddINotifyPropertyChangedInterface]publicclassEquipmentViewModel : Screen,IViewModel {public ObservableCollection<FileDTO> FileDTOList { get; set; } = new ObservableCollection<FileDTO>();private DispatcherTimer timer;publicEquipmentViewModel() { Environment.CurrentDirectory = AppDomain.CurrentDomain.BaseDirectory;//自启动 AutoStartHelper.AutoStart();//获取配置信息 XMLHelper xmlHelper = new XMLHelper(); FileDTOList = xmlHelper.XmlDocReader(); FileSystemWatcher();//开启定时器 timer = new DispatcherTimer(); timer.Interval = TimeSpan.FromSeconds(10); timer.Tick += timer_Tick; timer.Start(); Thread backThread = new Thread(StartRun); backThread.IsBackground = true; backThread.Start(); }publicvoidStartRun() {foreach (var fileDTO in FileDTOList) { Task.Run(() => {while (true) {if (fileDTO.BackBrushList.Count > 1) { Execute.OnUIThread(() => {if (fileDTO.BackBrush == Brushes.Red) { fileDTO.BackBrush = Brushes.Gray; }else { fileDTO.BackBrush = Brushes.Red; } }); Thread.Sleep(1000); } Thread.Sleep(100); } }); } }publicvoidBuildClick(object sender, MouseButtonEventArgs e) { StackPanel controls = sender as StackPanel;string title = null;foreach (var control in controls.Children) {if(control is Label) { title = (control as Label).Content.ToString(); } }foreach (var fileDTO in FileDTOList) {if (fileDTO.Title == title) { fileDTO.CurrentTime = DateTime.Now;if (fileDTO.BackBrushList.Contains(Brushes.Red)) { fileDTO.BackBrushList.Remove(Brushes.Red); fileDTO.BackBrush = Brushes.Gray; }return; } } }publicvoidFileSystemWatcher() {try {foreach (var fileDTO in FileDTOList) { FileSystemWatcher watcher = new FileSystemWatcher();try { LogHelper.logWrite($"the FileDTO is {fileDTO}");if (!string.IsNullOrEmpty(fileDTO?.MonitorPath)) { watcher.Path = fileDTO?.MonitorPath; }else { LogHelper.logWrite("the MonitorPath is null");continue; } }catch (ArgumentException e) { LogHelper.logWrite(e.Message);return; }//设置监视文件的哪些修改行为 watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName; watcher.Filter = "*.jpg";//添加事件句柄//当由FileSystemWatcher所指定的路径中的文件或目录的//大小、系统属性、最后写时间、最后访问时间或安全权限//发生更改时,更改事件就会发生 watcher.Changed += new FileSystemEventHandler(OnChanged); watcher.Created += new FileSystemEventHandler(OnChanged); watcher.Deleted += new FileSystemEventHandler(OnChanged); watcher.EnableRaisingEvents = true; fileDTO.CurrentTime = DateTime.Now; } }catch (Exception ex) { LogHelper.logWrite(ex.Message, ex.StackTrace); } }publicvoidOnChanged(object source, FileSystemEventArgs e) { Task.Run(() => {foreach (var fileDTO in FileDTOList) {//LogHelper.logWrite($"the FullPath = {e.FullPath},MonitorPath = {fileDTO.MonitorPath}");if (fileDTO.MonitorPath == Path.GetDirectoryName(e.FullPath)) { fileDTO.CurrentTime = DateTime.Now; Execute.OnUIThread(() => {if (fileDTO.BackBrushList.Contains(Brushes.Red)) { fileDTO.BackBrushList.Remove(Brushes.Red); fileDTO.BackBrush = Brushes.Gray; } });//return; } } }); }privatevoidtimer_Tick(object sender, EventArgs e) {foreach (var fileDTO in FileDTOList) {if(DiffSeconds(fileDTO.CurrentTime, DateTime.Now) >= fileDTO.TimeSpan) { Execute.OnUIThread(() => {if (!fileDTO.BackBrushList.Contains(Brushes.Red)) { fileDTO.BackBrushList.Add(Brushes.Red);var equipmentWindow = (Window)this.GetView();if (equipmentWindow.WindowState == WindowState.Minimized) { equipmentWindow.Show(); equipmentWindow.WindowState = WindowState.Normal; equipmentWindow.Activate(); } } LogHelper.logWrite($"The Alarm Equipment is {fileDTO.Title}"); }); } } }///<summary>/// 相差秒///</summary>///<param name="startTime"></param>///<param name="endTime"></param>///<returns></returns>publicdoubleDiffSeconds(DateTime startTime, DateTime endTime) { TimeSpan secondSpan = new TimeSpan(endTime.Ticks - startTime.Ticks);return secondSpan.TotalSeconds; } }}
功能主体都是在这里实现的,
Thread backThread = new Thread(StartRun); backThread.IsBackground = true;
通过背景线程去更新界面alarm显示;
FileSystemWatcher watcher = new FileSystemWatcher();
通过FileSystemWatcher 去监测设备上文件夹是否有文件更新,
publicvoidBuildClick(object sender, MouseButtonEventArgs e)
这个方法主要用来双击界面后消除设备的闪烁显示;
//开启定时器 timer = new DispatcherTimer(); timer.Interval = TimeSpan.FromSeconds(10); timer.Tick += timer_Tick; timer.Start();
开启定时器,用来检测是否超过设定时间,设备没有数据更新。以上就是此工具的所有功能了,如有疑问欢迎加我微信沟通.
源码下载:
网盘链接:https://pan.baidu.com/s/1kA4scA_3t8F3eeLy-dRWAA
提取码:6666