WPF 实现温度计

c299273a1fd2246ad3896ec6ca2bbbc0.png

01

代码如下

一、创建 Thermometer.cs 继承 Control代码如下。

7d1102fee3e732808e06306189d1587c.png

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代码如下

c0f8bd04ef7a5d8755d7a288678d08ba.png

<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

技术群:添加小编微信并备注进群

小编微信:mm1552923   

公众号:dotNet编程大全      

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WPF(Windows Presentation Foundation)是一种用于创建 Windows 应用程序的框架,它提供了丰富的图形和用户界面功能。实现像 XMind 这样的思维导图工具的过程如下: 1. 数据结构设计:首先需要设计思维导图的数据结构,包括节点(节点可能有不同的类型,如主题、子主题、注释等)、连接线等。可以使用树状结构或图结构来表示思维导图的组织关系。 2. 界面设计:使用 WPF 的图形和用户界面功能来设计思维导图的界面。可以使用画布(Canvas)来承载节点和连接线,通过鼠标事件来实现节点拖拽、连线等功能。可以为节点和连接线定义样式和模板,以美化界面和提供更多交互效果。 3. 数据绑定:将思维导图的数据模型与界面进行绑定,使得界面能够动态展示数据的变化。可以使用 WPF 的数据绑定机制,将节点的属性绑定到界面控件上,当属性值发生变化时,界面会自动更新。 4. 布局和自动排版:思维导图的节点可能会很多,因此需要实现自动排版来保证节点的布局整齐美观。可以使用 WPF 的布局控件如网格(Grid)、堆栈面板(StackPanel)等进行节点的布局,并根据节点之间的关系自动调整节点的位置和大小。 5. 导出和导入:实现将思维导图保存为文件或导入文件的功能,可以使用 WPF 的文件操作功能来实现。可以将思维导图保存为 XML、JSON 或其他格式,并提供打开、保存功能供用户使用。 通过以上步骤,就可以使用 WPF 实现类似 XMind 的思维导图工具。当然,具体的实现过程和功能细节还需要根据实际需求进行具体设计和开发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值