WPF 实现温度计
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF 实现温度计相关的知识,希望对你有一定的参考价值。
WPF开发者QQ群: 340500857 | 微信群 -> 进入公众号主页 加入组织
在WPF中没有现成的温度计控件,所以我们自己实现一个。
微信群人数太多入群请添加小编微信号
(yanjinhuawechat)或(W_Feng_aiQ)邀请入群
(需备注WPF开发者)
PS:有更好的方式欢迎推荐。
01
—
代码如下
一、创建 Thermometer.cs 继承 Control代码如下。
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace WPFDevelopers.Controls
public class Thermometer: Control
public static readonly DependencyProperty MaxValueProperty =
DependencyProperty.Register("MaxValue", typeof(double), typeof(Thermometer), new UIPropertyMetadata(40.0));
public double MaxValue
get return (double)GetValue(MaxValueProperty);
set SetValue(MaxValueProperty, value);
public static readonly DependencyProperty MinValueProperty =
DependencyProperty.Register("MinValue", typeof(double), typeof(Thermometer), new UIPropertyMetadata(-10.0));
public double MinValue
get return (double)GetValue(MinValueProperty);
set SetValue(MinValueProperty, value);
/// <summary>
/// 当前值
/// </summary>
public static readonly DependencyProperty CurrentValueProperty =
DependencyProperty.Register("CurrentValue", typeof(double), typeof(Thermometer), new UIPropertyMetadata(OnCurrentValueChanged));
private static void OnCurrentValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
Thermometer thermometer = d as Thermometer;
thermometer.CurrentValue = Convert.ToDouble(e.NewValue);
public double CurrentValue
get return (double)GetValue(CurrentValueProperty);
set
SetValue(CurrentValueProperty, value);
PaintPath();
/// <summary>
/// 步长
/// </summary>
public static readonly DependencyProperty IntervalProperty =
DependencyProperty.Register("Interval", typeof(double), typeof(Thermometer), new UIPropertyMetadata(10.0));
public double Interval
get return (double)GetValue(IntervalProperty);
set SetValue(IntervalProperty, value);
/// <summary>
/// 当前值的图形坐标点
/// </summary>
public static readonly DependencyProperty CurrentGeometryProperty =
DependencyProperty.Register("CurrentGeometry", typeof(Geometry), typeof(Thermometer), new PropertyMetadata(Geometry.Parse(@"M 2 132.8
a 4 4 0 0 1 4 -4
h 18
a 4 4 0 0 1 4 4
v 32.2
a 4 4 0 0 1 -4 4
h -18
a 4 4 0 0 1 -4 -4 z")));
public Geometry CurrentGeometry
get return (Geometry)GetValue(CurrentGeometryProperty);
set SetValue(CurrentGeometryProperty, value);
/// <summary>
/// 构造函数
/// </summary>
static Thermometer()
DefaultStyleKeyProperty.OverrideMetadata(typeof(Thermometer), new FrameworkPropertyMetadata(typeof(Thermometer)));
public override void OnApplyTemplate()
base.OnApplyTemplate();
PaintPath();
protected override void OnRender(DrawingContext drawingContext)
SolidColorBrush brush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#82848A"));
Rect rect = new Rect();
rect.Width = 30;
rect.Height = 169;
drawingContext.DrawRoundedRectangle(Brushes.Transparent,
new Pen(brush, 2d),
rect, 8d, 8d);
#region 华氏温度
drawingContext.DrawText(GetFormattedText("华"), new Point(-49, 115));
drawingContext.DrawText(GetFormattedText("氏"), new Point(-49, 115 + 14));
drawingContext.DrawText(GetFormattedText("温"), new Point(-49, 115 + 28));
drawingContext.DrawText(GetFormattedText("度"), new Point(-49, 115 + 42));
#endregion
#region 摄氏温度
drawingContext.DrawText(GetFormattedText("摄", FlowDirection.LeftToRight), new Point(75, 115));
drawingContext.DrawText(GetFormattedText("氏", FlowDirection.LeftToRight), new Point(75, 115 + 14));
drawingContext.DrawText(GetFormattedText("温", FlowDirection.LeftToRight), new Point(75, 115 + 28));
drawingContext.DrawText(GetFormattedText("度", FlowDirection.LeftToRight), new Point(75, 115 + 42));
#endregion
#region 画刻度
var total_Value = MaxValue - MinValue;
var cnt = total_Value / Interval;
var one_value = 161d / cnt;
for (int i = 0; i <= cnt; i++)
var formattedText = GetFormattedText($"MaxValue - (i * Interval)", FlowDirection.LeftToRight);
drawingContext.DrawText(formattedText, new Point(43, i * one_value - (formattedText.Height / 2d)));//减去字体高度的一半
formattedText = GetFormattedText($"(MaxValue - (i * Interval)) * 1.8d + 32d");
drawingContext.DrawText(formattedText, new Point(-13, i * one_value - (formattedText.Height / 2d)));
if (i != 0 && i != 5)
drawingContext.DrawLine(new Pen(Brushes.Black, 1d),
new Point(4, i * one_value), new Point(6, i * one_value));
drawingContext.DrawLine(new Pen(Brushes.Black, 1d),
new Point(24, i * one_value), new Point(26, i * one_value));
#endregion
private FormattedText GetFormattedText(string text, FlowDirection flowDirection = FlowDirection.RightToLeft)
return new FormattedText(text,
CultureInfo.CurrentUICulture,
flowDirection,
new Typeface("Microsoft YaHei"),
14d,
new SolidColorBrush((Color)ColorConverter.ConvertFromString("#82848A")));
/// <summary>
/// 动态计算当前值图形坐标点
/// </summary>
private void PaintPath()
var one_value = 161d / ((MaxValue - MinValue) / Interval);
var width = 26d;
var height = 169d - (MaxValue - CurrentValue) * (one_value / Interval);
var x = 2d;
var y = 169d - (169d - (MaxValue - CurrentValue) * (one_value / Interval));
CurrentGeometry = Geometry.Parse($@"M 2 y + 4
a 4 4 0 0 1 4 -4
h width - 8
a 4 4 0 0 1 4 4
v height - 8
a 4 4 0 0 1 -4 4
h -width - 8
a 4 4 0 0 1 -4 -4 z");
二、创建ThermometerExample.xaml代码如下
<UserControl x:Class="WPFDevelopers.Samples.ExampleViews.ThermometerExample"
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:wpfdev="https://github.com/yanjinhuagood/WPFDevelopers"
xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Border Background="White"
CornerRadius="12"
Width="400" Height="400"
Effect="StaticResource NormalShadowDepth">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Slider x:Name="PART_Slider" IsSnapToTickEnabled="True"
Value="10"
Minimum="-10"
Maximum="40"
Orientation="Vertical"
Height="300"/>
<Grid VerticalAlignment="Center"
Margin="160,0,0,0">
<Path Fill="StaticResource PrimaryMouseOverSolidColorBrush"
Stroke="StaticResource PrimaryMouseOverSolidColorBrush"
StrokeThickness="1" Opacity=".6"
Data="Binding ElementName=PART_Thermometer, Path=CurrentGeometry,Mode=TwoWay"/>
<wpfdev:Thermometer x:Name="PART_Thermometer"
CurrentValue="Binding ElementName=PART_Slider,Path=Value,Mode=TwoWay"/>
</Grid>
<TextBlock Text="Binding ElementName=PART_Thermometer,Path=CurrentValue,StringFormat=0℃"
FontSize="24" Grid.Column="1"
Foreground="StaticResource PrimaryPressedSolidColorBrush" FontFamily="Bahnschrift"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Border>
</Grid>
</UserControl>
02
—
效果预览
鸣谢素材提供者 - 帅嘉欣
源码地址如下
github:https://github.com/yanjinhuagood/WPFDevelopers.git
gitee:https://gitee.com/yanjinhua/WPFDevelopers.git
WPF开发者QQ群: 340500857
blogs: https://www.cnblogs.com/yanjinhua
Github:https://github.com/yanjinhuagood
出处:https://www.cnblogs.com/yanjinhua
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
转载请著名作者 出处 https://github.com/yanjinhuagood
扫一扫关注我们,
更多知识早知道!
点击阅读原文可跳转至源代码
以上是关于WPF 实现温度计的主要内容,如果未能解决你的问题,请参考以下文章