上節已經對本軟體的功能和意圖進行了詳細講解,這節就不再啰嗦,本節主要對功能實作和程式碼部份展開講解.
01
—
前台程式碼
前台XAML:
<Windowx: 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>
< styleTargetType="Label">
<SetterProperty="HorizontalAlignment"Value ="Center"/>
<SetterProperty="VerticalAlignment"Value ="Center"/>
<SetterProperty="FontSize"Value ="14"/>
<SetterProperty="FontWeight"Value ="Black"/>
</ style>
< styleTargetType="ListBox">
<SetterProperty="HorizontalAlignment"Value ="Left"/>
<SetterProperty="VerticalAlignment"Value ="Top"/>
<SetterProperty="FontSize"Value ="14"/>
<SetterProperty="FontWeight"Value ="Black"/>
<SetterProperty="ItemTemplate">
<Setter.Value>
<DataTemplate>
<BorderBorderBrush="Gray"BorderThickness="2"Margin="2" >
<StackPanelOrientation="Vertical"Background="{Binding BackBrush}"
cal:Message.Attach="[Event MouseLeftButtonUp]=[BuildClick($source,$eventArgs)]">
<ImageSource="../Image/Display.png"Width="100"Height="100" />
<LabelContent="{Binding Title}" />
</StackPanel>
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
<SetterProperty="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<WrapPanelOrientation="Horizontal" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</ style>
</Window.Resources>
<Grid>
<ListBoxx: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;
namespaceEquipmentMonitor.Model
{
[AddINotifyPropertyChangedInterface]
public classFileDTO
{
publicFileDTO()
{
BackBrushList = new ObservableCollection<Brush>();
BackBrushList.Add(Brushes.White);
BackBrush = Brushes.White;
CurrentTime = DateTime.Now;
}
publicstring Title { get; set; }
publicstring MonitorPath { get; set; }
publicint TimeSpan { get; set; }
public DateTime CurrentTime { get; set; }
public Brush BackBrush { get; set; }
public ObservableCollection<Brush> BackBrushList { get; set; }
publicoverridestringToString()
{
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;
namespaceEquipmentMonitor.Helper
{
public classAutoStartHelper
{
publicstaticvoidAutoStart(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;
namespaceEquipmentMonitor.Helper
{
public classLogHelper
{
publicstaticvoidlogWrite(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;
namespaceEquipmentMonitor.Helper
{
public classXMLHelper
{
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");
returnnull;
}
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);
returnnull;
}
}
}
}
③ 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;
namespaceEquipmentMonitor
{
[AddINotifyPropertyChangedInterface]
public classEquipmentViewModel : Screen,IViewModel
{
public ObservableCollection<FileDTO> FileDTOList { get; set; } = new ObservableCollection<FileDTO>();
private DispatcherTimer timer;
publicEquipmentViewModel()
{
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();
}
publicvoidStartRun()
{
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);
}
});
}
}
publicvoidBuildClick(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;
}
}
}
publicvoidFileSystemWatcher()
{
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);
}
}
publicvoidOnChanged(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;
}
}
});
}
privatevoidtimer_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>
publicdoubleDiffSeconds(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 去監測裝置上資料夾是否有檔更新,
publicvoidBuildClick(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
進群學習交流加 : mm1552923
如果喜歡我的文章,那麽
「在看」和轉發是對我最大的支持!