在学习和工作中使用WPF时,都离不开自定义控件的使用,今天分享一个自己在学习过程中使用到的一个自定义仪表盘控件,感觉挺不错的,在这里分享给大家。(我不是大佬,我只是好代码的搬运工,具体忘了是在那里偷师拿来的)
仪表控件后台逻辑其实不算复杂,相关的算法网上也有很多,主要是界面绘制这里比较重要,因为这关系到自定义控件的美观性。话不多说,开干
1、首先创建一个用户控件,然后就开始编写我们的布局文件,这里直接挂上代码来进行讲解
a、首先是那个Border,这个是作为整个仪表盘的底图,那些背景色之类的就通过Binding关联到定义好的依赖属性那里去
b、然后就是Canvas,这个画布是用来绘制刻度值那些东西的
c、紧跟的两个Path,和那个Border是绘制仪表盘的指针和圆心的
2、接着我们转到后台逻辑的编写,这里比较复杂的就是刻度线和刻度值的绘制了,由于我不擅长讲解这些,有兴趣的可以参考大佬的博客:WPF自定义控件(1)——仪表盘设计[1]
这里就直接简单粗暴的挂出代码
public partial class MeterPlate : UserControl
{
public int Value
{
get { return (int)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(int), typeof(MeterPlate),
new PropertyMetadata(default(int), new PropertyChangedCallback(OnValuePropertyChanged)));
public double Minimum
{
get { return (double)GetValue(MinimumProperty); }
set { SetValue(MinimumProperty, value); }
}
public static readonly DependencyProperty MinimumProperty =
DependencyProperty.Register("Minimum", typeof(double), typeof(MeterPlate),
new PropertyMetadata(double.NaN, new PropertyChangedCallback(OnPropertyChanged)));
public double Maximum
{
get { return (double)GetValue(MaximumProperty); }
set { SetValue(MaximumProperty, value); }
}
public static readonly DependencyProperty MaximumProperty =
DependencyProperty.Register("Maximum", typeof(double), typeof(MeterPlate),
new PropertyMetadata(double.NaN, new PropertyChangedCallback(OnPropertyChanged)));
public Brush PlateBackground
{
get { return (Brush)GetValue(PlateBackgroundProperty); }
set { SetValue(PlateBackgroundProperty, value); }
}
public static readonly DependencyProperty PlateBackgroundProperty =
DependencyProperty.Register("PlateBackground", typeof(Brush), typeof(MeterPlate), null);
public Brush PlateBorderBrush
{
get { return (Brush)GetValue(PlateBorderBrushProperty); }
set { SetValue(PlateBorderBrushProperty, value); }
}
public static readonly DependencyProperty PlateBorderBrushProperty =
DependencyProperty.Register("PlateBorderBrush", typeof(Brush), typeof(MeterPlate), null);
public Thickness PlateBorderThickness
{
get { return (Thickness)GetValue(PlateBorderThicknessProperty); }
set { SetValue(PlateBorderThicknessProperty, value); }
}
public static readonly DependencyProperty PlateBorderThicknessProperty =
DependencyProperty.Register("PlateBorderThickness", typeof(Thickness), typeof(MeterPlate), null);
public static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as MeterPlate).DrawScale();
}
public static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as MeterPlate).DrawAngle();
}
public MeterPlate()
{
InitializeComponent();
Loaded += MeterPlate_Loaded;
}
private void MeterPlate_Loaded(object sender, RoutedEventArgs e)
{
this.DrawScale();
}
///
/// 画表盘的刻度
///
private void DrawScale()
{
this.canvasPlate.Children.Clear();
for (double i = 0; i <= this.Maximum - this.Minimum; i++)
{
//添加刻度线
Line lineScale = new Line();
if (i % 10 == 0)
{
//注意Math.Cos和Math.Sin的参数是弧度,记得将角度转为弧度制
lineScale.X1 = 200 - 170 * Math.Cos(i * (270 / (this.Maximum - this.Minimum)) * Math.PI / 180);
lineScale.Y1 = 200 - 170 * Math.Sin(i * (270 / (this.Maximum - this.Minimum)) * Math.PI / 180);
lineScale.Stroke = new SolidColorBrush(Colors.White);
lineScale.StrokeThickness = 3;
//添加刻度值
TextBlock txtScale = new TextBlock();
txtScale.Text = (i + this.Minimum).ToString();
txtScale.Width = 34;
txtScale.TextAlignment = TextAlignment.Center;
txtScale.Foreground = new SolidColorBrush(Colors.White);
txtScale.RenderTransform = new RotateTransform() { Angle = 45, CenterX = 17, CenterY = 8 };
txtScale.FontSize = 18;
Canvas.SetLeft(txtScale, 200 - 155 * Math.Cos(i * (270 / (this.Maximum - this.Minimum)) * Math.PI / 180) - 17);
Canvas.SetTop(txtScale, 200 - 155 * Math.Sin(i * (270 / (this.Maximum - this.Minimum)) * Math.PI / 180) - 10);
this.canvasPlate.Children.Add(txtScale);
}
else
{
lineScale.X1 = 200 - 180 * Math.Cos(i * (270 / (this.Maximum - this.Minimum)) * Math.PI / 180);
lineScale.Y1 = 200 - 180 * Math.Sin(i * (270 / (this.Maximum - this.Minimum)) * Math.PI / 180);
lineScale.Stroke = new SolidColorBrush(Colors.White);
lineScale.StrokeThickness = 1;
}
lineScale.X2 = 200 - 190 * Math.Cos(i * (270 / (this.Maximum - this.Minimum)) * Math.PI / 180);
lineScale.Y2 = 200 - 190 * Math.Sin(i * (270 / (this.Maximum - this.Minimum)) * Math.PI / 180);
this.canvasPlate.Children.Add(lineScale);
}
}
private void DrawAngle()
{
double step = 270.0 / (this.Maximum - this.Minimum);
DoubleAnimation da = new DoubleAnimation(this.Value * step - 45, new Duration(TimeSpan.FromMilliseconds(200)));
this.rtPointer.BeginAnimation(RotateTransform.AngleProperty, da);
}
}
3、这样一个简单简洁的仪表盘控件就完成了,我也顺便写了一个简单的例子来测试,监测电脑CPU的使用率和让我们来看看效果吧