using System; using System.Windows; using System.Windows.Controls; using System.Collections.Generic; using Microsoft.Expression.Shapes; using System.Windows.Media; using System.Windows.Media.Animation; namespace CustomUI { /// /// 刻度盘控件 /// [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(300.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 { 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(10)); /// /// 获取或设置长刻度个数,用于设置刻度盘显示几个长刻度 /// 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 Skin 刻度盘样式 public static readonly DependencyProperty SkinProperty = DependencyProperty.Register("Skin", typeof(DashboardSkinEnum), typeof(Dashboard), new PropertyMetadata(DashboardSkinEnum.Speed)); /// /// 刻度盘样式 /// public DashboardSkinEnum Skin { get { return (DashboardSkinEnum)GetValue(SkinProperty); } set { SetValue(SkinProperty, 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 } }