WPF工控組態軟體之溫度計

来源:https://www.cnblogs.com/hsiang/archive/2022/12/20/16993460.html
-Advertisement-
Play Games

WPF以其豐富靈活的控制項樣式設計,相較於WinForm而言,一直是工控組態軟體的寵兒。經過前兩文章的學習,已經對WPF開發工控組態軟體有了一個基本的瞭解, 今天繼續學習溫度計的開發,僅供學習分享使用,如有不足之處,還請指正。 ...


WPF以其豐富靈活的控制項樣式設計,相較於WinForm而言,一直是工控組態軟體的寵兒。經過前兩文章的學習,已經對WPF開發工控組態軟體有了一個基本的瞭解, 今天繼續學習溫度計的開發,僅供學習分享使用,如有不足之處,還請指正。

各位關註【老碼識途】的朋友們,因出差期間,一直使用公司具有文件加密和監控功能的電腦,無法發佈原創文章。現在持續兩個月的出差終於結束了,又可以發佈原創博文了,後續會持續更新。

涉及知識點

 在本示例中,主要知識點如下:

  • WPF陰影效果,線性漸變的設置,主要設置溫度計的邊框,填充等效果,形成一種金屬質感。

  • WPF依賴屬性設置,主要設置最大溫度,最低溫度,和當前溫度值

  • WPF線條繪製,主要用於刻度

溫度計截圖

本示例主要實現功能為自定義刻度值,以及水銀條隨著當前溫度值變化。具體如下所示:

溫度計源碼

示例源碼分為以下2個部分:

1. Thermometer控制項

Thermometer控制項佈局

 1 <UserControl x:Class="WpfControl.UserControls.Thermometer"
 2              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
 5              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
 6              xmlns:local="clr-namespace:WpfControl.UserControls"
 7              mc:Ignorable="d" 
 8              d:DesignHeight="450" d:DesignWidth="150">
 9     <Grid>
10         <Grid.RowDefinitions>
11             <RowDefinition></RowDefinition>
12             <RowDefinition Height="auto"></RowDefinition>
13         </Grid.RowDefinitions>
14         <Rectangle StrokeThickness="7" RadiusX="40" RadiusY="15" Fill="White" />
15         <Rectangle StrokeThickness="7" RadiusX="40" RadiusY="15">
16             <Rectangle.Effect>
17                 <DropShadowEffect ShadowDepth="0" Direction="0" BlurRadius="7" />
18             </Rectangle.Effect>
19             <Rectangle.Stroke>
20                 <LinearGradientBrush StartPoint="0,1" EndPoint="1,0">
21                     <LinearGradientBrush.RelativeTransform>
22                         <RotateTransform Angle="40" CenterX="0.5" CenterY="0.5" />
23                     </LinearGradientBrush.RelativeTransform>
24                     <GradientStop Color="Black" />
25                     <GradientStop Color="White" Offset="0.7" />
26                 </LinearGradientBrush>
27             </Rectangle.Stroke>
28         </Rectangle>
29         <TextBlock Text="℃" HorizontalAlignment="Center" VerticalAlignment="Top" FontWeight="Bold" FontSize="20" Margin="0, 20" Foreground="#555"/>
30         <Canvas Name="MainCanvas" Width="75" Margin="0,70" />
31         <Border Width="10" RenderTransformOrigin="0.5,0.5" CornerRadius="5" Margin="0,50">
32             <Border.Effect>
33                 <DropShadowEffect ShadowDepth="0" Direction="0" Color="White" />
34             </Border.Effect>
35             <Border.Background>
36                 <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
37                     <GradientStop Color="lightGray" Offset="0" />
38                     <GradientStop Color="White" Offset="0.4" />
39                     <GradientStop Color="lightGray" Offset="1" />
40                 </LinearGradientBrush>
41             </Border.Background>
42             <Border Height="75" VerticalAlignment="Bottom" Name="BorValue">
43                 <Border.Background>
44                     <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
45                         <GradientStop Color="#CD3333"  />
46                         <GradientStop Color="#FFC0CB" Offset="0.4" />
47                         <GradientStop Color="#CD3333" Offset="1" />
48                     </LinearGradientBrush>
49                 </Border.Background>
50             </Border>
51         </Border>
52         <Border Height="25" Width="25" CornerRadius="15" VerticalAlignment="Bottom" Margin="0 0 0 30">
53             <Border.Effect>
54                 <DropShadowEffect Direction="0" ShadowDepth="0" />
55             </Border.Effect>
56             <Border.Background>
57                 <RadialGradientBrush Center="0.3,0.2" GradientOrigin="0.4,0.4">
58                     <GradientStop Color="White" Offset="0" />
59                     <GradientStop Color="#CD3333" Offset="1" />
60                 </RadialGradientBrush>
61             </Border.Background>
62         </Border>
63         <TextBox Grid.Row="1" Text="{Binding Value, UpdateSourceTrigger=PropertyChanged}" HorizontalContentAlignment="Center" BorderThickness="0" BorderBrush="AliceBlue" VerticalAlignment="Bottom" FontSize="20" Name="ThermometerValue" />
64     </Grid>
65 </UserControl>

依賴屬性設置及後臺生成刻度源碼,如下所示:

  1 namespace WpfControl.UserControls
  2 {
  3     /// <summary>
  4     /// Thermometer.xaml 的交互邏輯
  5     /// </summary>
  6     public partial class Thermometer : UserControl
  7     {
  8         public int Minmum
  9         {
 10             get { return (int)GetValue(MinmumProperty); }
 11             set { SetValue(MinmumProperty, value); }
 12         }
 13 
 14         public static readonly DependencyProperty MinmumProperty =
 15             DependencyProperty.Register("Minmum", typeof(int), typeof(Thermometer), new PropertyMetadata(1, new PropertyChangedCallback(OnPropertyValueChanged)));
 16 
 17 
 18         public int Maxmum
 19         {
 20             get { return (int)GetValue(MaxmumProperty); }
 21             set { SetValue(MaxmumProperty, value); }
 22         }
 23 
 24         public static readonly DependencyProperty MaxmumProperty =
 25             DependencyProperty.Register("Maxmum", typeof(int), typeof(Thermometer), new PropertyMetadata(10, new PropertyChangedCallback(OnPropertyValueChanged)));
 26 
 27 
 28 
 29         public double Value
 30         {
 31             get { return (double)GetValue(ValueProperty); }
 32             set { SetValue(ValueProperty, value);}
 33         }
 34 
 35         public static readonly DependencyProperty ValueProperty =
 36             DependencyProperty.Register("Value", typeof(double), typeof(Thermometer), new PropertyMetadata(0.0, new PropertyChangedCallback(OnPropertyValueChanged)));
 37 
 38         /// <summary>
 39         /// 當屬性值發生變化的時候直接更新UI內容
 40         /// </summary>
 41         /// <param name="d"></param>
 42         /// <param name="e"></param>
 43         private static void OnPropertyValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
 44         {
 45             (d as Thermometer)?.RefreshComponet();
 46         }
 47 
 48         private double step = 10;
 49 
 50         public Thermometer()
 51         {
 52             InitializeComponent();
 53             this.DataContext = this;
 54         }
 55 
 56         /// <summary>
 57         /// 刷新溫度計上面的內容適應定義大小
 58         /// </summary>
 59         /// <exception cref="NotImplementedException"></exception>
 60         private void RefreshComponet()
 61         {
 62             // 兩種方式觸發:尺寸變化、區間變化
 63             var h = this.MainCanvas.ActualHeight;//通過這個判斷界面元素是否載入
 64             if (h == 0) return;
 65             double w = 75;
 66             // 類型
 67             double stepCount = Maxmum - Minmum;// 在這個區間內多少個間隔
 68             step = h / (Maxmum - Minmum);// 每個間隔距離
 69 
 70             this.MainCanvas.Children.Clear();
 71 
 72             for (int i = 0; i <= stepCount; i++)
 73             {
 74                 Line line = new Line();
 75                 line.Y1 = i * step;
 76                 line.Y2 = i * step;
 77                 line.Stroke = Brushes.Black;
 78                 line.StrokeThickness = 1;
 79                 this.MainCanvas.Children.Add(line);
 80 
 81                 if (i % 10 == 0)
 82                 {
 83                     line.X1 = 15;
 84                     line.X2 = w - 15;
 85 
 86                     // 添加文字
 87                     TextBlock text = new TextBlock
 88                     {
 89                         Text = (Maxmum - i).ToString(),
 90                         Width = 20,
 91                         TextAlignment = TextAlignment.Center,
 92                         FontSize = 9,
 93                         Margin = new Thickness(0, -5, -4, 0)
 94                     };
 95                     Canvas.SetLeft(text, w - 15);
 96                     Canvas.SetTop(text, i * step);
 97                     this.MainCanvas.Children.Add(text);
 98 
 99                     // 添加文字
100                     text = new TextBlock
101                     {
102                         Text = (Maxmum - i).ToString(),
103                         Width = 20,
104                         TextAlignment = TextAlignment.Center,
105                         FontSize = 9,
106                         Margin = new Thickness(-4, -5, 0, 0)
107                     };
108                     Canvas.SetLeft(text, 0);
109                     Canvas.SetTop(text, i * step);
110                     this.MainCanvas.Children.Add(text);
111                 }
112                 else if (i % 5 == 0)
113                 {
114                     line.X1 = 20;
115                     line.X2 = w - 20;
116                 }
117                 else
118                 {
119                     line.X1 = 25;
120                     line.X2 = w - 25;
121                 }
122             }
123             ValueChanged();
124         }
125 
126 
127         private void ValueChanged() {
128             // 限定值的變化範圍 
129             var value = this.Value;
130             if (this.Value < this.Minmum)
131                 value = this.Minmum;
132             if (this.Value > this.Maxmum)
133                 value = this.Maxmum;
134 
135             // 溫度值與Border的高度的一個轉換
136             var newValue = value - this.Minmum;
137             newValue *= step;
138             newValue += 20;
139 
140             // 動畫
141             DoubleAnimation doubleAnimation = new DoubleAnimation(newValue, TimeSpan.FromMilliseconds(500));
142             this.BorValue.BeginAnimation(HeightProperty, doubleAnimation);
143         }
144 
145     }
146 
147 }

2. 控制項調用

用戶控制項不可以獨立展示,需要以視窗為載體,作為視窗的一部分展示,頁面調用如下所示:

 1 <Window
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:WpfControl"
 7         xmlns:UserControls="clr-namespace:WpfControl.UserControls" x:Class="WpfControl.TestWindow3"
 8         mc:Ignorable="d"
 9         Title="工控組態軟體--溫度計" Height="450" Width="1000" Loaded="Window_Loaded">
10     <Grid>
11         <Grid.ColumnDefinitions>
12             <ColumnDefinition></ColumnDefinition>
13             <ColumnDefinition></ColumnDefinition>
14             <ColumnDefinition></ColumnDefinition>
15             <ColumnDefinition></ColumnDefinition>
16             <ColumnDefinition></ColumnDefinition>
17             <ColumnDefinition></ColumnDefinition>
18             <ColumnDefinition></ColumnDefinition>
19             <ColumnDefinition></ColumnDefinition>
20         </Grid.ColumnDefinitions>
21         <Grid.RowDefinitions>
22             <RowDefinition></RowDefinition>
23         </Grid.RowDefinitions>
24         <UserControls:Thermometer Grid.Column="0" Grid.Row="0" x:Name="t1" Width="100" Height="370" HorizontalAlignment="Center"  VerticalAlignment="Center"/>
25         <UserControls:Thermometer Grid.Column="1" Grid.Row="0" x:Name="t2" Width="100" Height="370" HorizontalAlignment="Center"  VerticalAlignment="Center"/>
26         <UserControls:Thermometer Grid.Column="2" Grid.Row="0" x:Name="t3" Width="100" Height="370" HorizontalAlignment="Center"  VerticalAlignment="Center"/>
27         <UserControls:Thermometer Grid.Column="3" Grid.Row="0" x:Name="t4" Width="100" Height="370" HorizontalAlignment="Center"  VerticalAlignment="Center"/>
28         <UserControls:Thermometer Grid.Column="4" Grid.Row="0" x:Name="t5" Width="100" Height="370" HorizontalAlignment="Center"  VerticalAlignment="Center"/>
29         <UserControls:Thermometer Grid.Column="5" Grid.Row="0" x:Name="t6" Width="100" Height="370" HorizontalAlignment="Center"  VerticalAlignment="Center"/>
30         <UserControls:Thermometer Grid.Column="6" Grid.Row="0" x:Name="t7" Width="100" Height="370" HorizontalAlignment="Center"  VerticalAlignment="Center"/>
31         	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在我們描述堆之前,我們首先要明白一個概念,什麼是樹? 樹的概念及結構 1.樹的概念 樹是一種非線性的數據結構,它是由n(n>=0)個有限結點組成一個具有層次關係的集合。把它叫做樹是因為它看起來像一棵倒掛的樹,也就是說它是根在上,而葉在下的。 有一個特殊的結點,稱為根結點,根節點沒有前驅結點。除根節點 ...
  • 項目地址 這個項目是很久以前的,當時go能力有限,寫的不盡人意。剛好最近有加密文件的需求,所以就完善了相關邏輯。 之前的方案還依賴 Seek(offset int64, whence int) (int64, error) ,看了go很多源碼,都說Seek不可靠。所以目前改為純Reader和Writ ...
  • 書接上回,上一回我們按照“低耦合高內聚”的組織架構方針對項目的整體結構進行了優化,本回將會繼續編寫業務,那就是用戶的登錄邏輯,將之前用戶管理模塊中添加的用戶賬號進行賬號和密碼的校驗,校驗通過後留存當前登錄用戶的信息,過程中使用圖形驗證碼強制進行人機交互,防止賬號的密碼被暴力破解。 登錄邏輯 首先在邏 ...
  • 區塊鏈技術並不是什麼高級概念,它並不比量子力學、泡利不相容原則、哥德巴赫猜想更難以理解,但卻也不是什麼類似“時間就是金錢”這種婦孺皆知的淺顯道理。區塊鏈其實是一套統籌組織記錄的方法論,或者說的更準確一些,一種“去中心化”的組織架構系統。 去中心化 眾所周知,任何一個公司、組織、或者是機構,都遵循同一 ...
  • Java新手天坑! 想寫一篇新手避坑向的文章很久了,最近來到園子,終於有機會發表這篇文章了(文筆和技術都不咋地,大佬見諒,適用於剛入坑沒多久的新手群體) 在java中,經過一段學習的人對數組操作應該是瞭如指掌了,但是剛剛入門的小白來說,數組卻存在著一個隱藏的大坑,我們先用Python示例一下: #l ...
  • 我國目前並未出台專門針對網路爬蟲技術的法律規範,但在司法實踐中,相關判決已屢見不鮮,K 哥特設了“K哥爬蟲普法”專欄,本欄目通過對真實案例的分析,旨在提高廣大爬蟲工程師的法律意識,知曉如何合法合規利用爬蟲技術,警鐘長鳴,做一個守法、護法、有原則的技術人員。 案情介紹 四川省德昌縣人民檢察院起訴書指控 ...
  • JZ48 最長不含重覆字元的子字元串 描述 請從字元串中找出一個最長的不包含重覆字元的子字元串,計算該最長子字元串的長度。 示例1 輸入:"abcabcbb" 返回值:3 說明:因為無重覆字元的最長子串是"abc",所以其長度為 3。 方法1 思路 維護一個數組,想裡面添加元素,直至出現第一個重覆元 ...
  • 摘要:Fork/Join框架位於J.U.C(java.util.concurrent)中,是Java7中提供的用於執行並行任務的框架,其可以將大任務分割成若幹個小任務,最終彙總每個小任務的結果後得到最終結果。 本文分享自華為雲社區《如何使用Java7提供的Fork/Join框架實現高併發程式?》,作 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...