WPF开发冷风机组态及应用
Posted inet_ygssoftware
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF开发冷风机组态及应用相关的知识,希望对你有一定的参考价值。
冷风机组件开发和应用
VS2022
.NET6框架
冷风机组件开发演示
WPF主界面设计
WPF主界面托板设计
<Window x:Class="WpfConsolePannel.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfConsolePannel"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="1260">
<Grid Background="Black">
<Canvas Background="Transparent"
MouseWheel="Canvas_MouseWheel"
MouseLeftButtonDown="Canvas_MouseLeftButtonDown"
MouseLeftButtonUp="Canvas_MouseLeftButtonUp"
MouseMove="Canvas_MouseMove">
<Viewbox Canvas.Left="30" Canvas.Top="120" Name="mainView">
<Grid>
<Polygon VerticalAlignment="Center"
Fill="LightGray"
Points="0,200 150,0 1000,0 1200 200 0,200"
Stroke="LightGray"
StrokeThickness="2"/>
</Grid>
</Viewbox>
</Canvas>
</Grid>
</Window>
WPF托板拖动实现
/// <summary>
/// 视图缩放
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Canvas_MouseWheel(object sender, MouseWheelEventArgs e)
// 获取实际渲染的高度和宽度
var w = this.mainView.ActualWidth + e.Delta;
var h = this.mainView.ActualHeight + e.Delta;
if (w <100) w = 500;
if (h <100) h = 100;
this.mainView.Height = h;
this.mainView.Width = w;
// 设置画板缩放的左边位置
this.mainView.SetValue(Canvas.LeftProperty, (this.RenderSize.Width - this.mainView.Width) / 2);
bool _isMoving = false;
Point _point = new Point(0, 0);
double _left =0, _top = 0;
private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
_isMoving = true;
_point = e.GetPosition(sender as Canvas);
_left = double.Parse(this.mainView.GetValue(Canvas.LeftProperty).ToString()!);
_top = double.Parse(this.mainView.GetValue(Canvas.TopProperty).ToString()!);
private void Canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
_isMoving = false;
private void Canvas_MouseMove(object sender, MouseEventArgs e)
if (_isMoving)
Point currentPoint = e.GetPosition(sender as Canvas);
this.mainView.SetValue(LeftProperty, _left + (currentPoint.X - _point.X));
this.mainView.SetValue(TopProperty, _top+(currentPoint.Y - _point.Y));
冷风机自定义控件
初始化代码
<Border BorderThickness="1" Name="frame">
<Viewbox VerticalAlignment="Center" HorizontalAlignment="Center">
<Canvas Width="205" Height="245" Margin="5">
</Canvas>
</Viewbox>
</Border>
画风扇托板
<Polygon Points="0,70 40,10 205,10 180,70" Fill="#FFF" />
画风扇上座弧形
<Path Canvas.Left="50" Canvas.Top="20" Data="M0 0A60 15 0 0 0 120 0L120 25A60 15 0 0 1 0 25">
<Path.Fill>
<LinearGradientBrush EndPoint="1,0" StartPoint="0,0">
<GradientStop Color="#FFD6D6D6" Offset="0" />
<GradientStop Color="#FFFFFF" Offset="0.5" />
<GradientStop Color="#FFD6D6D6" Offset="1" />
</LinearGradientBrush>
</Path.Fill>
</Path>
<Ellipse Width="120" Height="30" Fill="#CCC" Canvas.Top="10" Canvas.Left="50" />
通过Path画风扇
<Border Canvas.Left="54" Canvas.Top="-30" >
<Viewbox Width="110" Height="110" RenderTransformOrigin="0.5,0.5">
<Viewbox.RenderTransform>
<TransformGroup>
<RotateTransform Angle="0" x:Name="rt" />
<ScaleTransform ScaleY="0.25" />
</TransformGroup>
</Viewbox.RenderTransform>
<Path Fill="White" Data="M240.16436182 107.8387919c-64.76383717 88.95385497-39.00023321 207.2195934 60.99957411 287.22561045 41.74629367 33.41554783 139.52456881 68.55895483 127.98494279 96.5132357-52.94651971 81.57960187-156.4946072 17.15516602-220.88818912-41.00578317-84.01711628-75.80978886-156.21691576-56.74163671-186.48529261 51.09524212C-10.71451204 617.03250262 48.74233051 765.65918238 143.5585623 806.54154713c97.59314685 42.05484037 202.8073843-5.33784855 283.36878357-128.54032568 20.48746395-31.40999788 29.68213938-91.08282334 81.3019111-61.30811948 38.50655955 22.21532312 28.4171006 72.53919947 5.52297551 110.61379388-18.29678704 30.39179594-36.68613723 61.3698287-59.30256954 88.55274511-78.77183221 94.56939496-53.77959402 163.86885964 69.20690087 187.44178602C645.74827583 1026.59666126 777.09637117 968.06545617 807.88927696 868.96043369c39.37048913-126.50392112-28.54051901-207.80583155-128.046652-271.21206545-32.11965444-20.45661001-92.37871738-31.16316105-60.38248135-83.02976894 21.50566722-34.77315109 71.15074161-22.83241521 111.81712478-4.75161041 34.06349519 15.11876146 60.99957344 36.25417276 88.02821618 60.69102741 85.34386493 77.32166513 152.4526527 57.11189197 183.18384861-53.16250194 32.27392681-115.82822468-30.42265054-264.8560143-126.93588558-301.81984297-108.85508144-41.71543973-239.2466847 3.45571702-303.3317199 145.35609104-15.36559829 22.15361392-16.10610946 68.0652805-47.73208892 56.30967159-30.23752292-11.29278919-32.67503733-45.69568436-28.20111769-70.65706794 10.55227868-58.50034983 37.79690298-106.29414861 87.5345425-146.5902752 61.80179382-50.07704018 57.54385709-108.33055316-11.13851617-155.84665985-89.57094706-61.86350302-265.53481626-28.38624599-332.5201856 63.52965167z m304.56590408 376.82741277a41.84597906 41.84597906 0 1 1-59.17915112 59.17915112 41.84597906 41.84597906 0 0 1 59.17915112-59.17915112z" />
</Viewbox>
</Border>
画外壳
<Grid Width="180" Height="180" Background="LightGray" Canvas.Top="70">
<Border VerticalAlignment="Top" Height="140" BorderThickness="10">
<Border.Background>
<DrawingBrush TileMode="Tile" ViewportUnits="Absolute" Viewport="1 0 25 1">
<DrawingBrush.Drawing>
<GeometryDrawing>
<GeometryDrawing.Pen>
<Pen Brush="#EEE" />
</GeometryDrawing.Pen>
<GeometryDrawing.Geometry>
<PathGeometry>
<PathFigure>
<LineSegment Point="10,0" />
<LineSegment Point="10,10" />
</PathFigure>
</PathGeometry>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Border.Background>
</Border>
<Grid VerticalAlignment="Bottom" Height="45" Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border Background="#AAA" Margin="2" />
<Border Background="#AAA" Margin="2" Grid.Column="1" />
</Grid>
</Grid>
<Grid Width="180" Height="180" Background="LightGray" Canvas.Top="70" Canvas.Left="180">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="29*"/>
<ColumnDefinition Width="7*"/>
</Grid.ColumnDefinitions>
<Grid.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="0.139" />
<SkewTransform AngleY="-67.4" />
</TransformGroup>
</Grid.RenderTransform>
<Border VerticalAlignment="Top" Height="140" BorderThickness="10" Grid.ColumnSpan="2">
<Border.Background>
<DrawingBrush TileMode="Tile" ViewportUnits="Absolute" Viewport="1 0 25 1">
<DrawingBrush.Drawing>
<GeometryDrawing>
<GeometryDrawing.Pen>
<Pen Brush="#EEE" />
</GeometryDrawing.Pen>
<GeometryDrawing.Geometry>
<PathGeometry>
<PathFigure>
<LineSegment Point="10,0" />
<LineSegment Point="10,10" />
</PathFigure>
</PathGeometry>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Border.Background>
</Border>
<Grid VerticalAlignment="Bottom" Height="45" Margin="5,0,5,5" Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border Background="#AAA" Margin="2" />
<Border Background="#AAA" Margin="2" Grid.Column="1" />
</Grid>
</Grid>
画指示灯
<Border Width="18" Height="18" CornerRadius="10" Canvas.Left="155" Canvas.Top="85">
<Border.Background>
<RadialGradientBrush>
<GradientStop Color="gray" Offset="0.5" x:Name="gsGreen" />
<GradientStop Color="White" />
</RadialGradientBrush>
</Border.Background>
</Border>
<Border Width="18" Height="18" CornerRadius="10" Canvas.Left="155" Canvas.Top="110">
<Border.Background>
<RadialGradientBrush>
<GradientStop Color="gray" Offset="0.5" x:Name="gsRed" />
<GradientStop Color="White" />
</RadialGradientBrush>
</Border.Background>
</Border>
VisualStateManager设置运行状态
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState Name="RunState">
<Storyboard>
<!--添加风扇旋转动画-->
<DoubleAnimation Duration="0:0:0.1" From="0" To="-360"
RepeatBehavior="Forever"
Storyboard.TargetName="rt"
Storyboard.TargetProperty="Angle"/>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="gsGreen"
Storyboard.TargetProperty="Color">
<DiscreteColorKeyFrame Value="Green" KeyTime="0" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState Name="StopState" />
</VisualStateGroup>
<VisualStateGroup>
<VisualState Name="FaultState">
<Storyboard>
<!--错误指示灯-->
<ColorAnimationUsingKeyFrames Storyboard.TargetName="gsRed"
Storyboard.TargetProperty="Color"
RepeatBehavior="Forever">
<DiscreteColorKeyFrame Value="Red" KeyTime="0:0:0.5" />
<DiscreteColorKeyFrame Value="Gray" KeyTime="0:0:1" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState Name="NormalState" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
添加依赖属性
public bool IsRunning
get return (bool)GetValue(IsRunningProperty);
set SetValue(IsRunningProperty, value);
// Using a DependencyProperty as the backing store for IsRunning. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsRunningProperty =
DependencyProperty.Register("IsRunning", typeof(bool), typeof(CoolingTower), new PropertyMetadata(default(bool),new PropertyChangedCallback(OnRunStateChanged)));
private static void OnRunStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
bool state = (bool)e.NewValue;
VisualStateManager.GoToState(d as CoolingTower, state ? "RunState" : "StopState", false);
public bool IsFault
get return (bool)GetValue(IsFaultProperty);
set SetValue(IsFaultProperty, value);
// Using a DependencyProperty as the backing store for IsRunning. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsFaultProperty =
DependencyProperty.Register("IsFault", typeof(bool), typeof(CoolingTower), new PropertyMetadata(default(bool), new PropertyChangedCallback(OnFaultStateChanged)));
private static void OnFaultStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
bool state = (bool)e.NewValue;
VisualStateManager.GoToState(d as CoolingTower, state ? "FaultState" : "NormalState", false);
自定义流动管道控件
窗口布局
<UserControl x:Class="WpfComponent.Controls.Pipeline"
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:WpfComponent.Controls"
mc:Ignorable="d"
d:DesignHeight="30" d:DesignWidth="500">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState Name="WEFlowState">
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation Duration="0:0:1" From="0" To="5"
Storyboard.TargetName="flowLine"
Storyboard.TargetProperty="StrokeDashOffset"
/>
</Storyboard>
</VisualState>
<VisualState Name="EEFlowState">
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation Duration="0:0:1" From="0" To="-5"
Storyboard.TargetName="flowLine"
Storyboard.TargetProperty="StrokeDashOffset"
/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border CornerRadius="Binding CapRadius, RelativeSource=RelativeSource AncestorType=UserControl,Mode=FindAncestor">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFCBCBCB" Offset="0.9"/>
<GradientStop Color="#FFFFFFFF" Offset="0.5"/>
<GradientStop Color="#FFCBCBCB" Offset="0.0"/>
</LinearGradientBrush>
</Border.Background>
<Border Margin="2" Name="border">
<Line X1="0" Y1="0" X2="Binding RelativeSource=RelativeSource Self,Path=ActualWidth"
Y2="0"
Stroke="Binding LiquidColor,RelativeSource=RelativeSource AncestorType=UserControl,Mode=FindAncestor"
StrokeThickness="Binding ElementName=border,Path=ActualHeight"
StrokeDashArray="2,3"
VerticalAlignment="Center"
Stretch="Fill"
StrokeDashCap="Round"
StrokeEndLineCap="Round"
StrokeStartLineCap="Round"
Name="flowLine" Opacity="0.3"
/>
</Border>
</Border>
</Grid>
</UserControl>
自定义依赖属性
public int Direction
get return (int)GetValue(DirectionProperty);
set SetValue(DirectionProperty, value);
// Using a DependencyProperty as the backing store for Direction. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DirectionProperty =
DependencyProperty.Register("Direction", typeof(int), typeof(Pipeline), new PropertyMetadata(default(int),new PropertyChangedCallback(OnDirectionChanged)));
/// <summary>
/// 设置状态
/// </summary>
/// <param name="d"></param>
/// <param name="e"></param>
/// <exception cref="NotImplementedException"></exception>
private static void OnDirectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
int value = int.Parse(e.NewValue.ToString()!);
VisualStateManager.GoToState(d as Pipeline, value == 1 ? "WEFlowState" : "EEFlowState",false);
/// <summary>
/// 设置液体颜色
/// </summary>
public Brush LiquidColor
get return (Brush)GetValue(LiquidColorProperty);
set SetValue(LiquidColorProperty, value);
// Using a DependencyProperty as the backing store for LiquidColor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty LiquidColorProperty =
DependencyProperty.Register("LiquidColor", typeof(Brush), typeof(Pipeline), new PropertyMetadata(Brushes.Red));
public int CapRadius
get return (int)GetValue(CapRadiusProperty);
set SetValue(CapRadiusProperty, value);
// Using a DependencyProperty as the backing store for CapRadius. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CapRadiusProperty =
DependencyProperty.Register("CapRadius", typeof(int), typeof(Pipeline), new PropertyMetadata(0));
界面组装组态应用
<component:CoolingTower Width="90" Height="110" HorizontalAlignment="Left" VerticalAlignment="Bottom"
Margin="125 0 0 100"
IsRunning="False"
IsFault="False" />
<component:CoolingTower Width="90" Height="110" HorizontalAlignment="Left" VerticalAlignment="Bottom"
Margin="100 0 0 60"
IsRunning="False"
IsFault="False" />
<component:CoolingTower Width="90" Height="110" HorizontalAlignment="Left" VerticalAlignment="Bottom"
Margin="75 0 0 10"
IsRunning="False"
IsFault="False" />
<component:Pipeline Height="10"
LiquidColor="Green"
Direction="1"
CapRadius="2"
Width="200"
VerticalAlignment="Top" Margin="207,53,805,0"/>
<component:Pipeline Height="10"
LiquidColor="Red"
Direction="1"
CapRadius="2"
Width="200"
VerticalAlignment="Top" Margin="180,97,832,0"/>
<component:Pipeline Height="10"
LiquidColor="Orange"
Direction="1"
CapRadius="2"
Width="210"
VerticalAlignment="Top" Margin="150,146,852,0"/>
<component:Pipeline Height="10"
LiquidColor="Orange"
Direction="1"
CapRadius="2"
Width="150"
VerticalAlignment="Top" Margin="352,149,710,0">
<component:Pipeline.RenderTransform>
<RotateTransform Angle="-60" />
</component:Pipeline.RenderTransform>
</component:Pipeline>
<component:Pipeline Height="10"
LiquidColor="Orange"
Direction="1"
CapRadius="2"
Width="210"
VerticalAlignment="Top" Margin="429,20,573,0"/>
<component:Pipeline Height="10"
LiquidColor="Orange"
Direction="-1"
CapRadius="2"
Width="150"
VerticalAlignment="Top" Margin="556,151,506,0">
<component:Pipeline.RenderTransform>
<RotateTransform Angle="-60" />
</component:Pipeline.RenderTransform>
</component:Pipeline>
以上是关于WPF开发冷风机组态及应用的主要内容,如果未能解决你的问题,请参考以下文章