当前位置:网站首页>C# WPF设备监控软件(经典)-下篇
C# WPF设备监控软件(经典)-下篇
2022-08-04 00:21:00 【dotNET跨平台】
上节已经对本软件的功能和意图进行了详细讲解,这节就不再啰嗦,本节主要对功能实现和代码部分展开讲解.
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
边栏推荐
猜你喜欢
RSS feeds WeChat public - feed43 asain
搭建好pytorch环境后,pip和conda指令不能用
Nanoprobes 棕榈酰纳米金相关说明书
Unity intercepts 3D images and the implementation of picture-in-picture PIP
Using matlab to solve the linear optimization problem based on matlab dynamic model of learning notes _11 】 【
微服务的简单介绍
免费的公共WiFi不要乱连,遭中间人攻击了吧?
伦敦银最新均线分析系统怎么操作?
小身材有大作用——光模块寿命分析(二)
Go编译原理系列7(Go源码调试)
随机推荐
View the version number of CUDA, pytorch, etc.
搭建好pytorch环境后,pip和conda指令不能用
伦敦银最新均线分析系统怎么操作?
2021年数据泄露成本报告解读
JS get parameter value of URL hyperlink
ENS域名注册量创历史新高 逆市增长之势?光环之下存在炒作风险
分布式事务框架 seata
轻量级网络整理及其在Yolov5上的实现
数据库扩容也可以如此丝滑,MySQL千亿级数据生产环境扩容实战
The longest substring that cannot have repeating characters in a leetcode/substring
A Preliminary Study of RSS Subscription to WeChat Official Account-feed43
DataBinding下的RecycleView适配器Adapter基类
JVM垃圾回收总结(未完待续)
【OpenCV图像处理】 图像拼接技术
HNUCM 您好中国
Nanoprobes Alexa Fluor 488 FluoroNanogold 偶联物
求解同余方程 数论 扩展欧几里得
BioVendor人Clara细胞蛋白(CC16)Elisa试剂盒检测步骤
扩展卡尔曼滤波EKF
【每日一题】899. 有序队列