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

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

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 = 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;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 == null){LogHelper.logWrite("xmlRoot is null");return null;}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 null;}}}
}

③ 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 = 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;}}}public void FileSystemWatcher(){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);}}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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/284109.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/284109.shtml
英文地址,請注明出處:http://en.pswp.cn/news/284109.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[轉]互聯網最大謠言:程序員35歲必淘汰?今天我就來擊碎他

朋友&#xff0c;只要你是程序員&#xff0c;你一定知道996和“程序員35歲必死”的言論。 這兩個話題在互聯網上的討論一次比一次激烈。 996工作制&#xff0c;眾所周知&#xff0c;每天早上9點到崗&#xff0c;一直待到晚上9點&#xff0c;每周工作6天&#xff0c;很多互聯網公…

【ArcGIS微課1000例】0057:將多波段柵格(影像.tif)背景設置為無數據nodata的方法

本文講解將多波段柵格(影像.tif)背景設置為無數據nodata的方法。 文章目錄 一、背景值識別二、背景值去除【推薦閱讀】: 【ArcGIS微課1000例】0056:將單波段柵格背景設置為無數據NoData的方法 一、背景值識別 可以用【識別】工具來獲取影像數據的背景值。 在背景上單擊,…

華為HCIA認證H12-811題庫新增

801、[單選題]178/832、在系統視圖下鍵入什么命令可以切換到用戶視圖? A quit B souter C system-view D user-view 試題答案&#xff1a;A 試題解析&#xff1a;在系統視圖下鍵入quit命令退出到用戶視圖。因此答案選A。 802、[單選題]“網絡管理員在三層交換機上創建了V…

經典Java微服務架構教程 微服務從開發到部署

圖書目錄腦圖&#xff1a; 本書根據開源項目整理&#xff0c;由于原在線文檔無法正常使用&#xff0c;本人重新在Github上重新布署了一套在線文檔。 書中講解非常詳細&#xff0c;并且有在線的視頻教程&#xff0c;另有在線文檔和在線的源碼。 書中的代碼由于PDF排版問題可能顯…

linux下redis安裝

轉自&#xff1a;http://blog.java1234.com/blog/articles/311.html Redis從一開始就只支持Linux&#xff0c;后面雖然有團隊搞出Window版本&#xff0c;但是我還是建議大伙安裝到Linux中。 準備工作 &#xff08;wm VirtualBox&#xff09; VMware 以及Xshell https://redis…

cobbler koan自動重裝系統

介紹 koan是kickstart-over-a-network的縮寫&#xff0c;它是cobbler的客戶端幫助程序&#xff0c;koan允許你通過網絡提供虛擬機&#xff0c;也允許你重裝已經存在的客戶端。當運行時&#xff0c;koan會從遠端的cobbler server獲取安裝信息&#xff0c;然后根據獲取的安裝信息…

Quartz.NET simple_demo

Quartz.NET是一個開源的作業調度框架&#xff0c;非常適合在平時的工作中&#xff0c;定時輪詢數據庫同步&#xff0c;定時郵件通知&#xff0c;定時處理數據等。 Quartz.NET允許開發人員根據時間間隔&#xff08;或天&#xff09;來調度作業。它實現了作業和觸發器的多對多關系…

Hello Playwright:(9)執行 JavaScript 代碼

Playwright 提供了大量的 API 用于與頁面元素交互&#xff0c;但是在某些場景下還是不能完全滿足要求。比如我們需要獲得包括元素本身的 HTML&#xff0c;但是目前只有下列 API :InnerHTMLAsync 返回元素內的 HTML 內容InnerTextAsync 返回元素內的文本內容而使用 JavaScript 執…

【PhotoScan精品教程】photoscan無法啟動此程序,因為計算機中丟失cholmod.dll解決辦法

安裝完航測軟件photoscan&#xff0c;打開時提示&#xff1a;無法啟動此程序&#xff0c;因為計算機中丟失 cholmod.dll解決辦法。 錯誤提示&#xff1a; 解決辦法&#xff1a; 并不是缺少該動態鏈接庫文件&#xff0c;而是補丁文件拷貝錯了。

什么是中臺?企業為什么要建中臺?從數據中臺到AI中臺。

從去年開始&#xff0c;好像就有一只無形的手一直將我與“微服務”、“平臺化”、“中臺化”撮合在一起&#xff0c;給我帶來了很多的困擾和思考與收獲。 故事的開始源于去年的技術雷達峰會&#xff0c;我在會上做了一場關于平臺崛起的主題分享&#xff08;《The Rise of Plat…

老司機帶你重構Android的v4包的部分源碼

版權聲明&#xff1a;本文為博主原創文章&#xff0c;未經博主允許不得轉載。https://www.jianshu.com/p/a08d754944c4 轉載請標明出處&#xff1a;https://www.jianshu.com/p/a08d754944c4 本文出自 AWeiLoveAndroid的博客 【前言】過年回家忙著干活&#xff0c;忙著給親戚的孩…

.NET靜態代碼織入——肉夾饃(Rougamo) 發布1.1.0

肉夾饃是什么肉夾饃(https://github.com/inversionhourglass/Rougamo)通過靜態代碼織入方式實現AOP的組件。.NET常用的AOP有Castle DynamicProxy、AspectCore等&#xff0c;以上兩種AOP組件都是通過運行時生成一個代理類執行AOP代碼的&#xff0c;肉夾饃則是在代碼編譯時直接修…

Msys2 國內源(2017.3.30)

確定可用&#xff01; Server https://mirrors.tuna.tsinghua.edu.cn/msys2/msys/$arch轉載于:https://www.cnblogs.com/baud/p/6644887.html

基于 IdentityServer3 實現 OAuth 2.0 授權服務【密碼模式(Resource Owner Password Credentials)】...

密碼模式&#xff08;Resource Owner Password Credentials Grant&#xff09;中&#xff0c;用戶向客戶端提供自己的用戶名和密碼。客戶端使用這些信息&#xff0c;向"服務商提供商"索要授權。基于之前的 IdentityServer3 實現 OAuth 2.0 授權服務【客戶端模式(Clie…

【GlobalMapper精品教程】035:用CASS自帶數據創建高程地形、等高線教程

本文講述globalmapper用CASS自帶數據創建高程地形、等高線教程。 文章目錄 1. 坐標生成點2. 點轉高程格網3. 生成等高線4. 保存等高線CASS自帶等高線數據dgx.dat預覽:包含點號、編碼、東坐標、北坐標、高程5列,可以不用做任何修改,在Globalmapper中生成點。 1. 坐標生成點 …

SaaS產品的免費試用到底該怎么做

”SaaS產品的免費試用&#xff0c;絕不僅僅只是開放產品試用期這么簡單&#xff0c;很多企業并沒有重視免費試用模式的搭建和轉化路徑“ 很多SaaS廠商的產品都會提供免費試用的機會&#xff0c;雖然試用的最終目標是促成用戶為產品價值付費&#xff0c;但是很多SaaS廠商在開放系…

【.NET6+WPF】WPF使用prism框架+Unity IOC容器實現MVVM雙向綁定和依賴注入

前言&#xff1a;在C/S架構上&#xff0c;WPF無疑已經是“桌面一霸”了。在.NET生態環境中&#xff0c;很多小伙伴還在使用Winform開發C/S架構的桌面應用。但是WPF也有很多年的歷史了&#xff0c;并且基于MVVM的開發模式&#xff0c;受到了很多開發者的喜愛。并且隨著工業化的進…

sql 中 limit 與 limit,offset連用的區別

① select * from table limit 2,1; #跳過2條取出1條數據&#xff0c;limit后面是從第2條開始讀&#xff0c;讀取1條信息&#xff0c;即讀取第3條數據 ② select * from table limit 2 offset 1; #從第1條&#xff08;不包括&#xff09;數據開始取出2條…

【ArcGIS Pro微課1000例】0022:基于DEM進行流域分析生成流域圖

文章目錄 一、填洼二、流向分析三、計算流域一、填洼 填洼Fill,在進行水文分析后續操作前,首先要對DEM進行填洼,創建無凹陷點的DEM。 填洼需要使用水文分析工具下的【填洼】。 確定輸入與輸出即可。 填洼結果: 二、流向分析 在ArcGIS中使用的是八方向流量建模(D8算法),工…

Spring配置文件中bean標簽的scope屬性

轉自&#xff1a;https://fj-sh-chz.iteye.com/blog/1775149 singleton &#xff08;默認屬性&#xff09; Spring將Bean放入Spring IOC容器的緩存池中&#xff0c;并將Bean引用返回給調用者&#xff0c;spring IOC繼續對這些Bean進行后續的生命管理。BeanFactory只管理一個共…