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