WPF实现好看可控的温度计
废话不多少,直接上代码
1 public class Thermometer : System.Windows.Controls.Control 2 { 3 4 public static readonly DependencyProperty MaxValueProperty = DependencyProperty.Register("MaxValue", typeof(double), typeof(Thermometer), new UIPropertyMetadata(40.0)); 5 6 public double MaxValue 7 { 8 get { return (double)GetValue(MaxValueProperty); } 9 10 set { SetValue(MaxValueProperty, value); } 11 } 12 13 public static readonly DependencyProperty MinValueProperty = DependencyProperty.Register("MinValue", typeof(double), typeof(Thermometer), new UIPropertyMetadata(-10.0)); 14 15 public double MinValue 16 { 17 get { return (double)GetValue(MinValueProperty); } 18 19 set { SetValue(MinValueProperty, value); } 20 } 21 22 /// <summary> 23 /// 当前值 24 /// </summary> 25 public static readonly DependencyProperty CurrentValueProperty = DependencyProperty.Register("CurrentValue", typeof(double), typeof(Thermometer), new UIPropertyMetadata(0.0)); 26 27 public double CurrentValue 28 { 29 get { return (double)GetValue(CurrentValueProperty); } 30 31 set 32 { 33 SetValue(CurrentValueProperty, value); 34 35 PaintPath(); 36 } 37 } 38 39 /// <summary> 40 /// 步长 41 /// </summary> 42 public static readonly DependencyProperty IntervalProperty = DependencyProperty.Register("Interval", typeof(double), typeof(Thermometer), new UIPropertyMetadata(10.0)); 43 44 public double Interval 45 { 46 get { return (double)GetValue(IntervalProperty); } 47 48 set { SetValue(IntervalProperty, value); } 49 } 50 51 /// <summary> 52 /// 当前值的图形坐标点 53 /// </summary> 54 public static readonly DependencyProperty CurrentGeometryProperty = DependencyProperty.Register("CurrentGeometry", typeof(Geometry), typeof(Thermometer), new PropertyMetadata(Geometry.Parse(@"M 2 132.8 55 a 4 4 0 0 1 4 -4 56 h 18 57 a 4 4 0 0 1 4 4 58 v 32.2 59 a 4 4 0 0 1 -4 4 60 h -18 61 a 4 4 0 0 1 -4 -4 z"))); 62 63 public Geometry CurrentGeometry 64 { 65 get { return (Geometry)GetValue(CurrentGeometryProperty); } 66 67 set { SetValue(CurrentGeometryProperty, value); } 68 } 69 70 /// <summary> 71 /// 构造函数 72 /// </summary> 73 static Thermometer() 74 { 75 DefaultStyleKeyProperty.OverrideMetadata(typeof(Thermometer), new FrameworkPropertyMetadata(typeof(Thermometer))); 76 } 77 78 public override void OnApplyTemplate() 79 { 80 base.OnApplyTemplate(); 81 82 PaintPath(); 83 } 84 85 protected override void OnRender(DrawingContext drawingContext) 86 { 87 SolidColorBrush brush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#63E0B4")); 88 89 Rect rect = new Rect(); 90 91 rect.Width = 30; 92 93 rect.Height = 169; 94 95 drawingContext.DrawRoundedRectangle(Brushes.Transparent, 96 new Pen(brush, 4d), 97 rect, 8d, 8d); 98 99 #region 华氏温度 100 101 FormattedText text = new FormattedText("华", 102 CultureInfo.CurrentUICulture, 103 FlowDirection.RightToLeft, 104 new Typeface("Source Han Sans CN"), 105 12d, 106 new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFFFFF"))); 107 108 drawingContext.DrawText(text, new Point(-49, 115)); 109 110 text = new FormattedText("氏", 111 CultureInfo.CurrentUICulture, 112 FlowDirection.RightToLeft, 113 new Typeface("Source Han Sans CN"), 114 12d, 115 new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFFFFF"))); 116 117 drawingContext.DrawText(text, new Point(-49, 115 + 14)); 118 119 text = new FormattedText("温", 120 CultureInfo.CurrentUICulture, 121 FlowDirection.RightToLeft, 122 new Typeface("Source Han Sans CN"), 123 12d, 124 new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFFFFF"))); 125 126 drawingContext.DrawText(text, new Point(-49, 115 + 28)); 127 128 text = new FormattedText("度", 129 CultureInfo.CurrentUICulture, 130 FlowDirection.RightToLeft, 131 new Typeface("Source Han Sans CN"), 132 12d, 133 new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFFFFF"))); 134 135 drawingContext.DrawText(text, new Point(-49, 115 + 42)); 136 137 #endregion 138 139 #region 摄氏温度 140 141 text = new FormattedText("摄", 142 CultureInfo.CurrentUICulture, 143 FlowDirection.LeftToRight, 144 new Typeface("Source Han Sans CN"), 145 12d, 146 new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFFFFF"))); 147 148 drawingContext.DrawText(text, new Point(75, 115)); 149 150 text = new FormattedText("氏", 151 CultureInfo.CurrentUICulture, 152 FlowDirection.LeftToRight, 153 new Typeface("Source Han Sans CN"), 154 12d, 155 new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFFFFF"))); 156 157 drawingContext.DrawText(text, new Point(75, 115 + 14)); 158 159 text = new FormattedText("温", 160 CultureInfo.CurrentUICulture, 161 FlowDirection.LeftToRight, 162 new Typeface("Source Han Sans CN"), 163 12d, 164 new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFFFFF"))); 165 166 drawingContext.DrawText(text, new Point(75, 115 + 28)); 167 168 text = new FormattedText("度", 169 CultureInfo.CurrentUICulture, 170 FlowDirection.LeftToRight, 171 new Typeface("Source Han Sans CN"), 172 12d, 173 new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFFFFF"))); 174 175 drawingContext.DrawText(text, new Point(75, 115 + 42)); 176 177 #endregion 178 179 #region 画刻度 180 181 var total_Value = MaxValue - MinValue; 182 183 var cnt = total_Value / Interval; 184 185 var one_value = 161d / cnt; 186 187 for (int i = 0; i <= cnt; i++) 188 { 189 FormattedText formattedText = new FormattedText($"{MaxValue - (i * Interval)}", 190 CultureInfo.CurrentUICulture, 191 FlowDirection.LeftToRight, 192 new Typeface("Source Han Sans CN"), 193 12d, 194 new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFFFFF"))); 195 196 drawingContext.DrawText(formattedText, new Point(43, i * one_value - (formattedText.Height / 2d)));//减去字体高度的一半 197 198 formattedText = new FormattedText($"{(MaxValue - (i * Interval)) * 1.8d + 32d}", 199 CultureInfo.CurrentUICulture, 200 FlowDirection.RightToLeft, 201 new Typeface("Source Han Sans CN"), 202 12d, 203 new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFFFFF"))); 204 205 drawingContext.DrawText(formattedText, new Point(-13, i * one_value - (formattedText.Height / 2d))); 206 207 if (i != 0 && i != 5) 208 { 209 drawingContext.DrawLine(new Pen(new SolidColorBrush((Color)ColorConverter.ConvertFromString("#ED538A")), 1d), 210 new Point(4, i * one_value), new Point(6, i * one_value)); 211 212 drawingContext.DrawLine(new Pen(new SolidColorBrush((Color)ColorConverter.ConvertFromString("#ED538A")), 1d), 213 new Point(24, i * one_value), new Point(26, i * one_value)); 214 } 215 } 216 217 #endregion 218 } 219 220 /// <summary> 221 /// 动态计算当前值图形坐标点 222 /// </summary> 223 private void PaintPath() 224 { 225 var one_value = 161d / ((MaxValue - MinValue) / Interval); 226 227 var width = 26d; 228 229 var height = 169d - (MaxValue - CurrentValue) * (one_value / Interval); 230 231 var x = 2d; 232 233 var y = 169d - (169d - (MaxValue - CurrentValue) * (one_value / Interval)); 234 235 //画当前值的三角形 236 CurrentGeometry = Geometry.Parse($@"M 2 {y + 4} 237 a 4 4 0 0 1 4 -4 238 h {width - 8} 239 a 4 4 0 0 1 4 4 240 v {height - 8} 241 a 4 4 0 0 1 -4 4 242 h -{width - 8} 243 a 4 4 0 0 1 -4 -4 z"); 244 } 245 }
1 <Border Width="280" Height="253" Background="#2E385A" CornerRadius="12" Margin="13,15,0,0"> 2 <StackPanel Orientation="Horizontal"> 3 <Grid HorizontalAlignment="Left" Margin="86,43,0,0"> 4 <Path Stroke="Red" StrokeThickness="0.5" Fill="Red" Data="{Binding ElementName=Layout_Control_Thermometer1, Path=CurrentGeometry,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/> 5 <control:Thermometer x:Name="Layout_Control_Thermometer1" CurrentValue="10"/> 6 </Grid> 7 <TextBlock Text="{Binding ElementName=Layout_Control_Thermometer1,Path=CurrentValue,StringFormat={}{0}℃}" FontSize="24" Foreground="#ED538A" FontFamily="Bahnschrift" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="100,0,0,0"/> 8 </StackPanel> 9 </Border>
做有梦想的一只咸鱼