當前位置: 妍妍網 > 碼農

C# WPF裝置監控軟體(經典)-下篇

2024-01-31碼農

上節已經對本軟體的功能和意圖進行了詳細講解,這節就不再啰嗦,本節主要對功能實作和程式碼部份展開講解.

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]public classFileDTO {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{public classAutoStartHelper {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{public classLogHelper {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{public classXMLHelper {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]public classEquipmentViewModel : 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

    進群學習交流加 : mm1552923

    如果喜歡我的文章,那麽

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