C# WPF設備監控軟件(經典)-下篇

2024年2月6日 21点热度 0人点赞

上節已經對本軟件的功能和意圖進行了詳細講解,這節就不再囉嗦,本節主要對功能實現和代碼部分展開講解.

01

前臺代碼

前臺XAML:

<Window x: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> <Style TargetType="Label"> <Setter Property="HorizontalAlignment" Value ="Center"/> <Setter Property="VerticalAlignment" Value ="Center"/> <Setter Property="FontSize" Value ="14"/> <Setter Property="FontWeight" Value ="Black"/></Style> <Style TargetType="ListBox"> <Setter Property="HorizontalAlignment" Value ="Left"/> <Setter Property="VerticalAlignment" Value ="Top"/> <Setter Property="FontSize" Value ="14"/> <Setter Property="FontWeight" Value ="Black"/> <Setter Property="ItemTemplate"> <Setter.Value> <DataTemplate> <Border BorderBrush="Gray" BorderThickness="2" Margin="2" > <StackPanel Orientation="Vertical" Background="{Binding BackBrush}" cal:Message.Attach="[Event MouseLeftButtonUp]=[BuildClick($source,$eventArgs)]"> <Image Source="../Image/Display.png" Width="100" Height="100" /> <Label Content="{Binding Title}" /> </StackPanel> </Border> </DataTemplate> </Setter.Value> </Setter> <Setter Property="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate> <WrapPanel Orientation="Horizontal" /> </ItemsPanelTemplate> </Setter.Value> </Setter></Style> </Window.Resources> <Grid> <ListBox x: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;
namespace EquipmentMonitor.Model{ [AddINotifyPropertyChangedInterface] public class FileDTO { public FileDTO() { BackBrushList = new ObservableCollection<Brush>(); BackBrushList.Add(Brushes.White); BackBrush = Brushes.White; CurrentTime = DateTime.Now; } public string Title { get; set; } public string MonitorPath { get; set; } public int TimeSpan { get; set; } public DateTime CurrentTime { get; set; } public Brush BackBrush { get; set; } public ObservableCollection<Brush> BackBrushList { get; set; }
public override string ToString() { 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;
namespace EquipmentMonitor.Helper{ public class AutoStartHelper { public static void AutoStart(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;
namespace EquipmentMonitor.Helper{ public class LogHelper { public static void logWrite(string Message, string StackTrace = ) { 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;
namespace EquipmentMonitor.Helper{ public class XMLHelper { 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 == ) { LogHelper.logWrite("xmlRoot is "); return ; }
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); return ; } } }}

③ 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;
namespace EquipmentMonitor{ [AddINotifyPropertyChangedInterface] public class EquipmentViewModel : Screen,IViewModel { public ObservableCollection<FileDTO> FileDTOList { get; set; } = new ObservableCollection<FileDTO>(); private DispatcherTimer timer; public EquipmentViewModel() { 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(); }
public void StartRun() { 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); } }); } }
public void BuildClick(object sender, MouseButtonEventArgs e) { StackPanel controls = sender as StackPanel; string title = ; 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; } }
} public void FileSystemWatcher() { try { foreach (var fileDTO in FileDTOList) { FileSystemWatcher watcher = new FileSystemWatcher(); try { LogHelper.logWrite($"the FileDTO is {fileDTO}"); if (!string.IsOrEmpty(fileDTO?.MonitorPath)) { watcher.Path = fileDTO?.MonitorPath; } else { LogHelper.logWrite("the MonitorPath is "); 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); } }
public void OnChanged(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; } } }); }
private void timer_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> public double DiffSeconds(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 去監測設備上文件夾是否有文件更新,

 public void BuildClick(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

進群學習交流加 : mm1552923

如果喜歡我的文章,那麼

在看”和轉發是對我最大的支持!