WPF自定义仪表盘控件

WPF自定义仪表盘控件

  • 一、前言
  • 二、功能实现

一、前言

在学习和工作中使用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的使用率和让我们来看看效果吧


    


    

你可能感兴趣的:(wpf,c#)