当前位置:网站首页>C # WPF equipment monitoring software (classic) - the next
C # WPF equipment monitoring software (classic) - the next
2022-08-04 00:32:00 【dotNET cross-platform】
The function and intent of this software have been explained in detail in the previous section,No more verbiage in this section,This section mainly explains the function implementation and code part.
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>The front-end code is surprisingly simple,主要就是一个ListBox ,Then by setting the template,Display pictures and labels on the interface
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下面的方法,After appending at the top of the class,Property changes are automatically notified to the interface,Instead of triggering one by one.
② 帮助类:
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);
}
}
}
}没啥好讲的,It is for the first time the software is opened,Add startup information to the registry,The software can start by itself after the next boot;
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:Configuration file reading helper class
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";
//添加事件句柄
//当由FileSystemWatcherof the file or directory in the specified path
//大小、系统属性、最后写时间、Last access time or security permissions
//发生更改时,A change event occurs
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;
}
}
}The main body of the function is implemented here,
Thread backThread = new Thread(StartRun);
backThread.IsBackground = true;Update the interface through the background threadalarm显示;
FileSystemWatcher watcher = new FileSystemWatcher();通过FileSystemWatcher To monitor the folder on the device for file updates,
public void BuildClick(object sender, MouseButtonEventArgs e)This method is mainly used to eliminate the flickering display of the device after double-clicking the interface;
//开启定时器
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(10);
timer.Tick += timer_Tick;
timer.Start();开启定时器,Used to detect whether the set time is exceeded,The device has no data updates.That's it for all the features of this tool,If you have any questions, please add me on WeChat.
源码下载:
链接:https://pan.baidu.com/s/1kA4scA_3t8F3eeLy-dRWAA
提取码:6666
边栏推荐
- dynamic memory two
- 动态内存二
- 【超详细】手把手教你搭建MongoDB集群搭建
- 2022年8月份DAMA-CDGA/CDGP数据治理认证招生简章
- Sqlnet. Ora file with the connection of authentication test
- 数据库扩容也可以如此丝滑,MySQL千亿级数据生产环境扩容实战
- VR全景拍摄线上展馆,3D全景带你沉浸体验
- 状态机实验
- NLP resources that must be used for projects [Classified Edition]
- outputBufferIndex = mDecode.dequeueOutputBuffer(bufferInfo, 0) 一直返回为-1
猜你喜欢
随机推荐
共享新能源充电桩充电站建设需要些什么流程及资料?
2023年第六届亚太应用数学与统计学国际会议(AMS 2023)
XSLT – 服务器端概述
【性能优化】MySQL常用慢查询分析工具
POE交换机全方位解读(上)
我的祖国
七夕佳节即将来到,VR全景云游为你神助攻
typescript54-泛型约束
米哈游--测试开发提前批
XSS - Bypass for loop filtering
MPLS Comprehensive Experiment
c语言分层理解(c语言指针(上))
高斯推断推导
ES6高级-迭代器与生成器的用法
重新认识浏览器的渲染过程
LeetCode第三题(Longest Substring Without Repeating Characters)三部曲之三:两次优化
Salesforce's China business may see new changes, rumors may be closing
Justin Sun: Web3.0 and the Metaverse will assist mankind to enter the online world more comprehensively
The world's first mass production, with the most fixed points!How does this AVP Tier1 lead?
After building the pytorch environment, the pip and conda commands cannot be used









