WPF 自定义控件完成库容表盘显示效果

先看一下显示效果:

WPF 自定义控件完成库容表盘显示效果_第1张图片

       需要注意的地方有以下几点:

  1. 表盘的刻度分部,长刻度和短刻度显示。
  2. 在数值80W时,需要更改刻度盘的颜色渐变。
  3. 在数值80W时,更改库容总数背景的显示,也是颜色渐变。刻度盘控件属性定义:

刻度盘的定义:

using Microsoft.Expression.Shapes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace Dashboard_Demo
{
    /// 
    /// 刻度盘控件
    /// 
    /// add by zhidanfeng 2017.2.19
    [TemplatePart(Name = "PART_IncreaseCircle", Type = typeof(Arc))]
    public class Dashboard : Control
    {
        private Arc PART_IncreaseCircle;
        /// 
        /// 保存角度变化前的角度值(用于动画)
        /// 
        private double OldAngle;

        #region Constructors
        static Dashboard()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(Dashboard), new FrameworkPropertyMetadata(typeof(Dashboard)));
        }
        #endregion

        #region 依赖属性

        #region Angle 刻度盘起始角度
        /// 
        /// 刻度盘起始角度依赖属性
        /// 
        public static readonly DependencyProperty StartAngleProperty =
            DependencyProperty.Register(
                "StartAngle",
                typeof(double),
                typeof(Dashboard),
                new PropertyMetadata(0d));

        /// 
        /// 刻度盘起始角度
        /// 
        public double StartAngle
        {
            get { return (double)GetValue(StartAngleProperty); }
            set { SetValue(StartAngleProperty, value); }
        }
        #endregion

        #region Angle 刻度盘结束角度依赖属性
        /// 
        /// 刻度盘结束角度依赖属性
        /// 
        public static readonly DependencyProperty EndAngleProperty =
            DependencyProperty.Register(
                "EndAngle",
                typeof(double),
                typeof(Dashboard),
                new PropertyMetadata(0d));

        /// 
        /// 刻度盘结束角度依赖属性
        /// 
        public double EndAngle
        {
            get { return (double)GetValue(EndAngleProperty); }
            set
            {
                SetValue(EndAngleProperty, value);
            }
        }
        #endregion

        #region Minimum 最小值
        /// 
        /// 最小值依赖属性,用于Binding
        /// 
        public static readonly DependencyProperty MinimumProperty =
            DependencyProperty.Register(
                "Minimum",
                typeof(double),
                typeof(Dashboard),
                new PropertyMetadata(0.0));

        /// 
        /// 获取或设置最小值.
        /// 
        /// 最小值.
        public double Minimum
        {
            get { return (double)GetValue(MinimumProperty); }
            set { SetValue(MinimumProperty, value); }
        }
        #endregion

        #region Maximum 最大值
        /// 
        /// 最大值依赖属性,用于Binding
        /// 
        public static readonly DependencyProperty MaximumProperty =
            DependencyProperty.Register(
                "Maximum",
                typeof(double),
                typeof(Dashboard),
                new PropertyMetadata(100.0));

        /// 
        /// 获取或设置最大值.
        /// 
        /// 最大值.
        public double Maximum
        {
            get { return (double)GetValue(MaximumProperty); }
            set { SetValue(MaximumProperty, value); }
        }
        #endregion

        #region Value 当前值
        /// 
        /// 最大值依赖属性,用于Binding
        /// 
        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register(
                "Value",
                typeof(double),
                typeof(Dashboard),
                new PropertyMetadata(0.0, new PropertyChangedCallback(OnValuePropertyChanged)));

        /// 
        /// 获取或设置当前值
        /// 
        public double Value
        {
            get
            {
                if (PART_IncreaseCircle == null)
                    return (double)GetValue(ValueProperty);

                if ((double)GetValue(ValueProperty) > 800000d)
                {
                    LinearGradientBrush brush = new LinearGradientBrush();
                    brush.StartPoint = new Point(0, 0);
                    brush.EndPoint = new Point(1, 0);
                    brush.GradientStops.Add(new GradientStop((Color)ColorConverter.ConvertFromString("#f0b046"), 0));
                    brush.GradientStops.Add(new GradientStop((Color)ColorConverter.ConvertFromString("#e83a2d"), 1));
                    PART_IncreaseCircle.Stroke = brush;
                }
                else
                {
                    LinearGradientBrush brush = new LinearGradientBrush();
                    brush.StartPoint = new Point(0, 0);
                    brush.EndPoint = new Point(1, 0);
                    brush.GradientStops.Add(new GradientStop((Color)ColorConverter.ConvertFromString("#1ccabd"), 0));
                    brush.GradientStops.Add(new GradientStop((Color)ColorConverter.ConvertFromString("#458ffc"), 1));
                    PART_IncreaseCircle.Stroke = brush;
                }
                return (double)GetValue(ValueProperty);

            }
            set { SetValue(ValueProperty, value); }
        }

        private static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Dashboard dashboard = d as Dashboard;
            dashboard.OldAngle = dashboard.Angle;
            dashboard.SetAngle();
            dashboard.TransformAngle();
        }
        #endregion

        #region LongTickCount 长刻度个数
        public static readonly DependencyProperty LongTickCountProperty =
            DependencyProperty.Register(
                "LongTickCount",
                typeof(int),
                typeof(Dashboard),
                new PropertyMetadata(5));

        /// 
        /// 获取或设置长刻度个数,用于设置刻度盘显示几个长刻度
        /// 
        public int LongTickCount
        {
            get { return (int)GetValue(LongTickCountProperty); }
            set { SetValue(LongTickCountProperty, value); }
        }
        #endregion

        #region ShortTickCount 短刻度个数
        public static readonly DependencyProperty ShortTickCountProperty =
            DependencyProperty.Register(
                "ShortTickCount",
                typeof(int),
                typeof(Dashboard),
                new PropertyMetadata(3));

        /// 
        /// 获取或设置两个长刻度之间的短刻度的个数
        /// 
        public int ShortTickCount
        {
            get { return (int)GetValue(ShortTickCountProperty); }
            set { SetValue(ShortTickCountProperty, value); }
        }
        #endregion

        #region TickDurtion 刻度改变时的动画显示时长
        public static readonly DependencyProperty TickDurtionProperty = DependencyProperty.Register("TickDurtion"
            , typeof(Duration)
            , typeof(Dashboard),
            new PropertyMetadata(new Duration(TimeSpan.FromMilliseconds(400))));

        /// 
        /// 刻度改变时的动画显示时长
        /// 
        public Duration TickDurtion
        {
            get { return (Duration)GetValue(TickDurtionProperty); }
            set { SetValue(TickDurtionProperty, value); }
        }
        #endregion

        #region ShortTicksBrush 短刻度颜色
        public static readonly DependencyProperty ShortTicksBrushProperty = DependencyProperty.Register("ShortTicksBrush"
            , typeof(Brush)
            , typeof(Dashboard));

        /// 
        /// 短刻度颜色
        /// 
        public Brush ShortTicksBrush
        {
            get { return (Brush)GetValue(ShortTicksBrushProperty); }
            set { SetValue(ShortTicksBrushProperty, value); }
        }
        #endregion

        #region LongTicksBrush 长刻度颜色
        public static readonly DependencyProperty LongTicksBrushProperty = DependencyProperty.Register("LongTicksBrush"
            , typeof(Brush)
            , typeof(Dashboard));

        /// 
        /// 长刻度颜色
        /// 
        public Brush LongTicksBrush
        {
            get { return (Brush)GetValue(LongTicksBrushProperty); }
            set { SetValue(LongTicksBrushProperty, value); }
        }
        #endregion

        #region Content
        public object Content
        {
            get { return (object)GetValue(ContentProperty); }
            set { SetValue(ContentProperty, value); }
        }

        public static readonly DependencyProperty ContentProperty =
            DependencyProperty.Register("Content", typeof(object), typeof(Dashboard));
        #endregion

        #region ContentTemplate
        public DataTemplate ContentTemplate
        {
            get { return (DataTemplate)GetValue(ContentTemplateProperty); }
            set { SetValue(ContentTemplateProperty, value); }
        }

        public static readonly DependencyProperty ContentTemplateProperty =
            DependencyProperty.Register("ContentTemplate", typeof(DataTemplate), typeof(Dashboard));
        #endregion

        #endregion

        #region Private依赖属性

        #region Angle 刻度盘当前值所对应的角度
        /// 
        /// 刻度盘当前值所对应的角度依赖属性
        /// 
        public static readonly DependencyProperty AngleProperty =
            DependencyProperty.Register(
                "Angle",
                typeof(double),
                typeof(Dashboard),
                new PropertyMetadata(0d));

        /// 
        /// 刻度盘当前值所对应的角度
        /// 
        public double Angle
        {
            get { return (double)GetValue(AngleProperty); }
            private set { SetValue(AngleProperty, value); }
        }
        #endregion

        #region ShortTicks 短刻度线集合
        /// 
        /// 短刻度线依赖属性,用于Binding
        /// 
        public static readonly DependencyProperty ShortTicksProperty =
            DependencyProperty.Register(
                "ShortTicks",
                typeof(IList),
                typeof(Dashboard),
                new PropertyMetadata(null));

        /// 
        /// 获取或设置短刻度线,用于绑定PathListBox的ItemsSource
        /// 
        /// 短刻度线.
        public IList ShortTicks
        {
            get { return (IList)GetValue(ShortTicksProperty); }
            private set { SetValue(ShortTicksProperty, value); }
        }
        #endregion

        #region LongTicks 长刻度线集合
        /// 
        /// 长刻度线依赖属性,用于Binding
        /// 
        public static readonly DependencyProperty LongTicksProperty =
            DependencyProperty.Register(
                "LongTicks",
                typeof(IList),
                typeof(Dashboard),
                new PropertyMetadata(null));

        /// 
        /// 获取或设置长刻度线,用于绑定PathListBox的ItemsSource
        /// 
        /// 长刻度线.
        public IList LongTicks
        {
            get { return (IList)GetValue(LongTicksProperty); }
            private set { SetValue(LongTicksProperty, value); }
        }
        #endregion

        #region LongTicks 长刻度线上显示的数字
        /// 
        /// 长刻度线依赖属性,用于Binding
        /// 
        public static readonly DependencyProperty NumberListProperty =
            DependencyProperty.Register(
                "NumberList",
                typeof(IList),
                typeof(Dashboard),
                new PropertyMetadata(null));

        /// 
        /// 获取或设置长刻度线,用于绑定PathListBox的ItemsSource
        /// 
        /// 长刻度线.
        public IList NumberList
        {
            get { return (IList)GetValue(NumberListProperty); }
            private set { SetValue(NumberListProperty, value); }
        }
        #endregion

        #endregion

        #region 重载
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            this.PART_IncreaseCircle = GetTemplateChild("PART_IncreaseCircle") as Arc;

            this.SetTicks();
            this.SetAngle();
            this.TransformAngle();
        }
        #endregion

        #region Private方法
        /// 
        /// 设置刻度线
        /// 
        private void SetTicks()
        {
            List numbers = new List();
            List shortticks = new List();
            List longticks = new List();

            for (int i = 0; i < this.LongTickCount; i++)
            {
                numbers.Add(Math.Round(this.Minimum + (this.Maximum - this.Minimum) / (this.LongTickCount - 1) * i));
                longticks.Add(new object());
            }

            for (int i = 0; i < (this.LongTickCount - 1) * (this.ShortTickCount + 1) + 1; i++)
            {
                shortticks.Add(new object());
            }

            this.ShortTicks = shortticks;
            this.LongTicks = longticks;
            this.NumberList = numbers;
        }

        /// 
        /// 根据当前值设置圆弧的EndAngle
        /// 
        private void SetAngle()
        {
            if (this.Value < this.Minimum)
            {
                this.Angle = this.StartAngle;
                return;
            }

            if (this.Value > this.Maximum)
            {
                this.Angle = this.EndAngle;
                return;
            }

            var diff = this.Maximum - this.Minimum;
            var valueDiff = this.Value - this.Minimum;
            this.Angle = this.StartAngle + (this.EndAngle - this.StartAngle) / diff * valueDiff;
        }

        /// 
        /// 角度值变化动画
        /// 
        private void TransformAngle()
        {
            if (this.PART_IncreaseCircle != null)
            {
                DoubleAnimation doubleAnimation = new DoubleAnimation(this.OldAngle, this.Angle, this.TickDurtion);
                this.PART_IncreaseCircle.BeginAnimation(Arc.EndAngleProperty, doubleAnimation);
            }
        }
        #endregion
    }
}

设置刻度盘的style:


    
    
        
            
            

            
            

            
            
                
                    
                        
                    
                
                
                    
                
            

            
            
                
                    
                        
                    
                
                
                    
                
            

            
            
                
                    
                        
                        
                    
                
                
                    
                
            

            


            
            
            

            

            
        
    

    
        
            
        
    

    

    
        
        
    
    
        
        
    
    
        
        
    

    
        
        
    
    
        
        
    
    
        
        
    
  • 库容总数背景渐变实现:
  • 
                
                    
                    
                    
                    
                
            
    
            
                
                    
                    
                    
                    
                
            

    实现效果(低于80W):

  • WPF 自定义控件完成库容表盘显示效果_第2张图片

    高于80W时显示:

  • WPF 自定义控件完成库容表盘显示效果_第3张图片

    csdn下载地址:https://download.csdn.net/download/chulijun3107/88058570

  • github:GitHub - chulijun3107/Dashboard_Demo: WPF userControl

你可能感兴趣的:(wpf)