WPF工控组态软件之温度计

  • WPF工控组态软件之温度计已关闭评论
  • 28 次浏览
  • A+
所属分类:.NET技术
摘要

WPF以其丰富灵活的控件样式设计,相较于WinForm而言,一直是工控组态软件的宠儿。经过前两文章的学习,已经对WPF开发工控组态软件有了一个基本的了解, 今天继续学习温度计的开发,仅供学习分享使用,如有不足之处,还请指正。

WPF以其丰富灵活的控件样式设计,相较于WinForm而言,一直是工控组态软件的宠儿。经过前两文章的学习,已经对WPF开发工控组态软件有了一个基本的了解, 今天继续学习温度计的开发,仅供学习分享使用,如有不足之处,还请指正。

WPF工控组态软件之温度计

各位关注【老码识途】的朋友们,因出差期间,一直使用公司具有文件加密和监控功能的电脑,无法发布原创文章。现在持续两个月的出差终于结束了,又可以发布原创博文了,后续会持续更新。

涉及知识点

 在本示例中,主要知识点如下:

  • 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         <UserControls:Thermometer Grid.Column="7" Grid.Row="0" x:Name="t8" Width="100" Height="370" HorizontalAlignment="Center"  VerticalAlignment="Center"/> 32     </Grid> 33 </Window>

控件赋值,在窗口加载时,为控件赋初始值,如下所示:

 1 namespace WpfControl  2 {  3     /// <summary>  4     /// TestWindow3.xaml 的交互逻辑  5     /// </summary>  6     public partial class TestWindow3 : Window  7     {  8         public TestWindow3()  9         { 10             InitializeComponent(); 11         } 12  13         private void Window_Loaded(object sender, RoutedEventArgs e) 14         { 15             var controls = new Thermometer[8] { t1, t2 , t3, t4 , t5, t6 , t7, t8 }; 16             for (int i = 0; i < 8; i++) { 17                 controls[i].Maxmum = 100; 18                 controls[i].Minmum = -20; 19                 controls[i].Value = 10*(i+1); 20             } 21         } 22     } 23 }

注意:在实际业务中,可以通过对应的传输协议【如:Modbus等】从硬件获取,并实时的显示在页面中。

源码下载

关注【老码识途】公众号,然后回复MCGS即可,如下所示:

WPF工控组态软件之温度计

 

备注

以上就是本篇文章的全部内容,旨在抛砖引玉,共同学习,一起进步。学习编程,从关注【老码识途】开始!!!