当前位置:网站首页>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
边栏推荐
- Talking about the future development direction of my country's industrial parks
- 国内首发可视化智能调优平台,小龙带你玩转KeenTune UI
- typescript50-交叉类型和接口之间的类型说明
- Spinnaker调用Jenkins API 返回403错误
- 查看CUDA、pytorch等的版本号
- Eight things to pay attention to in spot silver
- Web3 安全风险令人生畏?应该如何应对?
- 电子组装行业对MES管理系统的需求分析
- 【超详细教程】LVS+KeepAlived高可用部署实战应用
- LeetCode 19:删除链表的倒数第 N 个结点
猜你喜欢
随机推荐
Modulo operation (MOD)
教你如何定位不合理的SQL?并优化之
vscode插件设置——Golang开发环境配置
共享新能源充电桩充电站建设需要些什么流程及资料?
动态内存二
600MHz频段来了,它会是新的黄金频段吗?
2022-08-03: What does the following go code output?A: 2; B: 3; C: 1; D: 0.package main import "fmt" func main() { slice := []i
sqlnet.ora文件与连接认证方式的小测试
伦敦银最新均线分析系统怎么操作?
Go编译原理系列7(Go源码调试)
ML18-自然语言处理
typescript50-交叉类型和接口之间的类型说明
FastDFS 一文读懂
Getting started with MATLAB 3D drawing command plot3
MPLS Comprehensive Experiment
LeetCode 19:删除链表的倒数第 N 个结点
研究生新生培训第四周:MobileNetV1, V2, V3
互斥锁、读写锁、自旋锁,以及原子操作指令xaddl、cmpxchg的使用场景剖析
Justin Sun was invited to attend the 36氪 Yuan Universe Summit and delivered a keynote speech
SQL优化的一些建议,希望可以帮到和我一样被SQL折磨的你