wpf 仪表盘
1 、效果如图

2 代码编写
A 、 前台页面 新建一个前台页面 Insrunment.xaml
<Grid> <Ellipse Fill="{Binding PlateBackground, RelativeSource={ RelativeSource AncestorType=UserControl,Mode=FindAncestor}}" Name="backEill" Width="250" Height="250"/> <Canvas Name="mainCanvas" Width="{Binding Width,ElementName=backEill}" Height="{Binding Height,ElementName=backEill}"/> <!--内部的圆圈没刻度的--> <Path Data="" Stroke="White" StrokeThickness="4" Name="circle" RenderTransformOrigin="0.5,0.5" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Width="{Binding Width, ElementName=backEill}" Height="{Binding Height, ElementName=backEill}"> <Path.RenderTransform> <RotateTransform Angle="-45"/> </Path.RenderTransform> </Path> <!--指针--> <Path Data="" Fill="Green" Name="point" RenderTransformOrigin="0.5,0.5" Width="{Binding Width,ElementName=backEill }" Height="{Binding Height,ElementName=backEill}"> <Path.RenderTransform> <RotateTransform Angle="-45" x:Name="rtpoint"/> </Path.RenderTransform> </Path> <!--圆心--> <Border Width="20" Height="20" CornerRadius="10"> <Border.Background> <RadialGradientBrush> <GradientStop Color="White" Offset="0.583" /> <GradientStop Color="#FF97B5BD" Offset="1" /> </RadialGradientBrush> </Border.Background> </Border> </Grid>
B、 后台代码
/// <summary> /// Insrunment.xaml 的交互逻辑 /// </summary> public partial class Insrunment : UserControl { public int Value { get { return (int)this.GetValue(ValueProperty); } set { this.SetValue(ValueProperty, value); } } public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(int), typeof(Insrunment), new PropertyMetadata(default(int), new PropertyChangedCallback(OnPropertyChanged))); /// <summary> /// 大刻度 /// </summary> public int BigScaleValue { get { return (int)GetValue(BigScaleValueProperty); } set { SetValue(BigScaleValueProperty, value); } } // Using a DependencyProperty as the backing store for BigScaleValue. This enables animation, styling, binding, etc... public static readonly DependencyProperty BigScaleValueProperty = DependencyProperty.Register("BigScaleValue", typeof(int), typeof(Insrunment), new PropertyMetadata(default(int), new PropertyChangedCallback(OnPropertyChanged))); // 代码片段propdp public int MinValue { get { return (int)GetValue(MinValueProperty); } set { SetValue(MinValueProperty, value); } } public static readonly DependencyProperty MinValueProperty = DependencyProperty.Register("MinValue", typeof(int), typeof(Insrunment), new PropertyMetadata(default(int), new PropertyChangedCallback(OnPropertyChanged))); public int MaxValue { get { return (int)GetValue(MaxValueProperty); } set { SetValue(MaxValueProperty, value); } } // Using a DependencyProperty as the backing store for MaxValue. This enables animation, styling, binding, etc... public static readonly DependencyProperty MaxValueProperty = DependencyProperty.Register("MaxValue", typeof(int), typeof(Insrunment), new PropertyMetadata(default(int), new PropertyChangedCallback(OnPropertyChanged))); //底盘颜色 public Brush PlateBackground { get { return (Brush)GetValue(PlateBackgroundProperty); } set { SetValue(PlateBackgroundProperty, value); } } // Using a DependencyProperty as the backing store for PlateBackground. This enables animation, styling, binding, etc... public static readonly DependencyProperty PlateBackgroundProperty = DependencyProperty.Register("PlateBackground", typeof(Brush), typeof(Insrunment), new PropertyMetadata(default(Brush))); /// <summary> /// 字体大小 /// </summary> public int ScaleTextSize { get { return (int)GetValue(ScaleTextSizeProperty); } set { SetValue(ScaleTextSizeProperty, value); } } // Using a DependencyProperty as the backing store for ScaleTextSize. This enables animation, styling, binding, etc... public static readonly DependencyProperty ScaleTextSizeProperty = DependencyProperty.Register("ScaleTextSize", typeof(int), typeof(Insrunment), new PropertyMetadata(default(int), new PropertyChangedCallback(OnPropertyChanged))); /// <summary> /// 刻度颜色 /// </summary> public Brush ScaleColor { get { return (Brush)GetValue(ScaleColorProperty); } set { SetValue(ScaleColorProperty, value); } } // Using a DependencyProperty as the backing store for ScaleColor. This enables animation, styling, binding, etc... public static readonly DependencyProperty ScaleColorProperty = DependencyProperty.Register("ScaleColor", typeof(Brush), typeof(Insrunment), new PropertyMetadata(default(Brush), new PropertyChangedCallback(OnPropertyChanged))); /// <summary> /// 变化的时候调用下面方法 /// </summary> /// <param name="d"></param> /// <param name="e"></param> public static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { (d as Insrunment).Refresh(); } public Insrunment() { InitializeComponent(); this.SizeChanged += Insrunment_SizeChanged; } void Insrunment_SizeChanged(object sender, SizeChangedEventArgs e) { double min = Math.Min(this.RenderSize.Width, this.RenderSize.Height); this.Width = min; this.Height = min; } //https://blog.csdn.net/weixin_45178215/article/details/118379606?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link&utm_relevant_index=1 private void Refresh() { double radius = this.backEill.Width / 2; if (double.IsNaN(radius)) { return; } if (MaxValue == 0) { return; } if (ScaleTextSize == 0) { return; } this.mainCanvas.Children.Clear(); //int min = 0, max = 100; double setp = 270.0 / (MaxValue - MinValue); //刻度 就是算一个圆上的坐标 可以百度搜索查看公式, 用正弦 余弦计算而出来的 //sinA=(y2-y1)/r ==>y2=y1+r*sinA // cosA=(x2-x1)/r=>x2=x1+rcosA; //弧度=角度*π/180 // x2 = x1 + rcos(角度*π/180); //y2=r*sinA(弧度*π/180)+y1; for (int i = 0; i < MaxValue - MinValue; i++) { Line lineScal = new Line(); //lineScal.X1 = 100; //lineScal.Y1 = 100; //lineScal.X2 = 200; //lineScal.Y2 = 200; // -45 逆时针旋转 //里面的点 -13 -20 的话就靠近右边 lineScal.X1 = radius - (radius - 13) * Math.Cos((i * setp - 45) * Math.PI / 180); lineScal.Y1 = radius - (radius - 13) * Math.Sin((i * setp - 45) * Math.PI / 180); // 外面的点 lineScal.X2 = radius - (radius - 8) * Math.Cos((i * setp - 45) * Math.PI / 180); lineScal.Y2 = radius - (radius - 8) * Math.Sin((i * setp - 45) * Math.PI / 180); lineScal.Stroke = ScaleColor; lineScal.StrokeThickness = 2; this.mainCanvas.Children.Add(lineScal); } // 大刻度 // int scalSie = 10;//BigScaleValue setp = 270.0 / BigScaleValue; //刻度文字 int scaleText = MinValue; for (int i = 0; i <= BigScaleValue; i++) { Line lineScal = new Line(); //里面的点 -13 -20 的话就靠近右边 lineScal.X1 = radius - (radius - 20) * Math.Cos((i * setp - 45) * Math.PI / 180); lineScal.Y1 = radius - (radius - 20) * Math.Sin((i * setp - 45) * Math.PI / 180); // 外面的点 lineScal.X2 = radius - (radius - 8) * Math.Cos((i * setp - 45) * Math.PI / 180); lineScal.Y2 = radius - (radius - 8) * Math.Sin((i * setp - 45) * Math.PI / 180); lineScal.Stroke = ScaleColor; lineScal.StrokeThickness = 2; this.mainCanvas.Children.Add(lineScal); //数字刻度 TextBlock text = new TextBlock(); text.Width = 34; text.TextAlignment = TextAlignment.Center; text.FontSize = ScaleTextSize; scaleText = MinValue + (MaxValue - MinValue) / BigScaleValue * i; text.Text = scaleText.ToString(); text.Foreground = ScaleColor; Canvas.SetLeft(text, radius - (radius - 36) * Math.Cos((i * setp - 45) * Math.PI / 180) - 17); Canvas.SetTop(text, radius - (radius - 36) * Math.Sin((i * setp - 45) * Math.PI / 180) - 10); this.mainCanvas.Children.Add(text); } //内部的弧线 string data = "M{0} {1} A{0} {0} 0 1 1 {1} {2}"; data = string.Format(data, radius / 2, radius, radius * 1.5); var conver = TypeDescriptor.GetConverter(typeof(Geometry)); this.circle.Data = (Geometry)conver.ConvertFrom(data); //具体指针到某个方向 setp = 270.0 / (MaxValue - MinValue); // this.rtpoint.Angle = this.Value * setp - 45; DoubleAnimation da = new DoubleAnimation(((int)(this.Value - this.MinValue) * setp) - 45, new Duration(TimeSpan.FromMilliseconds(200))); rtpoint.BeginAnimation(RotateTransform.AngleProperty, da); //指针 data = "M{0} {1} ,{1} {2}, {1} {3}"; data = string.Format(data, radius * 0.3, radius, radius - 5, radius + 5); this.point.Data = (Geometry)conver.ConvertFrom(data); } }
C 、调用
xmlns:zxc="clr-namespace:WPF4"
<zxc:Insrunment Value="{Binding InermentValue}" MinValue="0" MaxValue="100" BigScaleValue="10" PlateBackground="Orange" ScaleTextSize="16" ScaleColor="White"/>

浙公网安备 33010602011771号