WPF 仪表盘示例

WPF 仪表盘示例

**一.添加一个自定义控件 Dashboard
Microsoft.Expression.Drawing文件安装
使用Blend的绘制功能,需要引用 Microsoft.Expression.Drawing 库文件,

导入两个命名空间:Microsoft.Expression.Controls.dll 和 Microsoft.Expression.Drawing.dll
Themes/Generic.xaml代码:**

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WPF0317a"
    xmlns:Converters="clr-namespace:WPF0317a.Converters"
    xmlns:ec="http://schemas.microsoft.com/expression/2010/controls"
    xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing">


    <Converters:WordAngleConverter x:Key="WordAngleConverter" />

    <DataTemplate x:Key="DefaultLabelPanel" x:Shared="False">
        <Border Width="70" Margin="0,0,0,20" HorizontalAlignment="Center" VerticalAlignment="Bottom"
                BorderBrush="#00A0FB" BorderThickness="1" CornerRadius="3" Padding="0,2"
                SnapsToDevicePixels="True" UseLayoutRounding="True">
            <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Agency FB" Foreground="White"
                       Text="{Binding Path=Value,
                                      StringFormat={}{0:N1}KW,
                                      RelativeSource={RelativeSource Mode=FindAncestor,
                                                                     AncestorType={x:Type local:Dashboard}}}" />
        </Border>
    </DataTemplate>

    <ControlTemplate x:Key="Speed" TargetType="{x:Type local:Dashboard}">
        <Grid>
            <Ellipse Fill="#190E1C" />
            <Grid Margin="20">
                <ed:Arc x:Name="PART_IncreaseCircle" ArcThickness="8" ArcThicknessUnit="Pixel" Fill="#BB0104"
                        RenderTransformOrigin="0.5,0.5"
                        StartAngle="{TemplateBinding StartAngle}"
                        Stretch="None" />
                <ed:Arc x:Name="DoubleCircle" ArcThickness="8" ArcThicknessUnit="Pixel"
                        EndAngle="{TemplateBinding EndAngle}"
                        StartAngle="{TemplateBinding StartAngle}"
                        Stretch="None" Stroke="#00A0FB" StrokeThickness="1" />

                <ec:PathListBox x:Name="ShoartTick" IsHitTestVisible="False"
                                ItemsSource="{TemplateBinding ShortTicks}">
                    <ec:PathListBox.ItemTemplate>
                        <DataTemplate>
                            <Border Width="1" Height="8" Background="White" SnapsToDevicePixels="True"
                                    UseLayoutRounding="True" />
                        </DataTemplate>
                    </ec:PathListBox.ItemTemplate>
                    <ec:PathListBox.LayoutPaths>
                        <ec:LayoutPath Distribution="Even" Orientation="OrientToPath"
                                       SourceElement="{Binding ElementName=ShortTickPath}" />
                    </ec:PathListBox.LayoutPaths>
                </ec:PathListBox>

                <ec:PathListBox x:Name="LongTick" IsHitTestVisible="False"
                                ItemsSource="{TemplateBinding LongTicks}">
                    <ec:PathListBox.ItemTemplate>
                        <DataTemplate>
                            <Border Width="1" Height="13" Background="White" SnapsToDevicePixels="True"
                                    UseLayoutRounding="True" />
                        </DataTemplate>
                    </ec:PathListBox.ItemTemplate>
                    <ec:PathListBox.LayoutPaths>
                        <ec:LayoutPath Distribution="Even" Orientation="OrientToPath"
                                       SourceElement="{Binding ElementName=LongTickPath}" />
                    </ec:PathListBox.LayoutPaths>
                </ec:PathListBox>

                <ec:PathListBox x:Name="Number" IsHitTestVisible="False"
                                ItemsSource="{TemplateBinding NumberList}">
                    <ec:PathListBox.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding}" />
                        </DataTemplate>
                    </ec:PathListBox.ItemTemplate>
                    <ec:PathListBox.LayoutPaths>
                        <ec:LayoutPath Distribution="Even" Orientation="OrientToPath"
                                       SourceElement="{Binding ElementName=NumberPath}" />
                    </ec:PathListBox.LayoutPaths>
                </ec:PathListBox>

                <ed:Arc x:Name="LongTickPath" Margin="0" ArcThickness="0" ArcThicknessUnit="Pixel"
                        EndAngle="{TemplateBinding EndAngle}"
                        StartAngle="{TemplateBinding StartAngle}"
                        Stretch="None" />

                <ed:Arc x:Name="ShortTickPath" Margin="5" ArcThickness="0" ArcThicknessUnit="Pixel"
                        EndAngle="{TemplateBinding EndAngle}"
                        StartAngle="{TemplateBinding StartAngle}"
                        Stretch="None" />

                <ed:Arc x:Name="NumberPath" Margin="20" ArcThickness="0" ArcThicknessUnit="Pixel"
                        EndAngle="{TemplateBinding EndAngle}"
                        StartAngle="{TemplateBinding StartAngle}"
                        Stretch="None" />

                <Ellipse Width="15" Height="15" Stroke="Black">
                    <Ellipse.Fill>
                        <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                            <GradientStop Offset="0" Color="#FF2C2C2C" />
                            <GradientStop Offset="0.997" Color="Black" />
                        </LinearGradientBrush>
                    </Ellipse.Fill>
                </Ellipse>
                <Ellipse Width="10" Height="10" Stroke="#FFFFCA02" />
                <ed:RegularPolygon x:Name="Finger" Width="4" Height="50" Fill="#FFFFCA02"
                                   PointCount="3" RenderTransformOrigin="0.5,1.118" Stretch="Fill">
                    <ed:RegularPolygon.RenderTransform>
                        <TransformGroup>
                            <ScaleTransform />
                            <SkewTransform />
                            <RotateTransform Angle="{Binding EndAngle, ElementName=PART_IncreaseCircle}" />
                            <TranslateTransform Y="-31" />
                        </TransformGroup>
                    </ed:RegularPolygon.RenderTransform>
                </ed:RegularPolygon>
            </Grid>
            <ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" />
        </Grid>
    </ControlTemplate>

    <ControlTemplate x:Key="Flow" TargetType="{x:Type local:Dashboard}">
        <Grid>
            <ed:Arc x:Name="DoubleCircle" Margin="50" ArcThickness="1" ArcThicknessUnit="Pixel"
                    EndAngle="{TemplateBinding EndAngle}"
                    SnapsToDevicePixels="True"
                    StartAngle="{TemplateBinding StartAngle}"
                    Stretch="None" Stroke="#746E7A" StrokeThickness="1" UseLayoutRounding="True" />

            <ed:Arc x:Name="PART_IncreaseCircle" Margin="50" ArcThickness="1" ArcThicknessUnit="Pixel"
                    RenderTransformOrigin="0.5,0.5"
                    StartAngle="{TemplateBinding StartAngle}"
                    Stretch="None" Stroke="Red" StrokeThickness="1" />

            <ec:PathListBox x:Name="ShoartTick" IsHitTestVisible="False"
                            ItemsSource="{TemplateBinding ShortTicks}">
                <ec:PathListBox.ItemTemplate>
                    <DataTemplate>
                        <Border Width="1" Height="8"
                                Background="{Binding ShortTicksBrush,
                                                     RelativeSource={RelativeSource AncestorType={x:Type local:Dashboard}}}"
                                SnapsToDevicePixels="True" UseLayoutRounding="False" />
                    </DataTemplate>
                </ec:PathListBox.ItemTemplate>
                <ec:PathListBox.LayoutPaths>
                    <ec:LayoutPath Distribution="Even" Orientation="OrientToPath"
                                   SourceElement="{Binding ElementName=ShortTickPath}" />
                </ec:PathListBox.LayoutPaths>
            </ec:PathListBox>

            <ec:PathListBox x:Name="LongTick" IsHitTestVisible="False"
                            ItemsSource="{TemplateBinding LongTicks}">
                <ec:PathListBox.ItemTemplate>
                    <DataTemplate>
                        <Border Width="1" Height="13"
                                Background="{Binding LongTicksBrush,
                                                     RelativeSource={RelativeSource AncestorType={x:Type local:Dashboard}}}"
                                SnapsToDevicePixels="True" UseLayoutRounding="False" />
                    </DataTemplate>
                </ec:PathListBox.ItemTemplate>
                <ec:PathListBox.LayoutPaths>
                    <ec:LayoutPath Distribution="Even" Orientation="OrientToPath"
                                   SourceElement="{Binding ElementName=LongTickPath}" />
                </ec:PathListBox.LayoutPaths>
            </ec:PathListBox>

            <ec:PathListBox x:Name="Number" IsHitTestVisible="False"
                            ItemsSource="{TemplateBinding NumberList}">
                <ec:PathListBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock RenderTransformOrigin="0.5,0.5" Text="{Binding}">
                            <!--<TextBlock.RenderTransform>
                                    <TransformGroup>
                                        <ScaleTransform />
                                        <SkewTransform />
                                        <RotateTransform Angle="{Binding}" />
                                        <TranslateTransform />
                                    </TransformGroup>
                                </TextBlock.RenderTransform>-->
                        </TextBlock>
                    </DataTemplate>
                </ec:PathListBox.ItemTemplate>
                <ec:PathListBox.LayoutPaths>
                    <ec:LayoutPath Distribution="Even" Orientation="OrientToPath"
                                   SourceElement="{Binding ElementName=NumberPath}" />
                </ec:PathListBox.LayoutPaths>
            </ec:PathListBox>

            <ed:Arc x:Name="LongTickPath" Margin="0" ArcThickness="0" ArcThicknessUnit="Pixel"
                    EndAngle="{TemplateBinding EndAngle}"
                    StartAngle="{TemplateBinding StartAngle}"
                    Stretch="None" />

            <ed:Arc x:Name="ShortTickPath" Margin="5" ArcThickness="0" ArcThicknessUnit="Pixel"
                    EndAngle="{TemplateBinding EndAngle}"
                    StartAngle="{TemplateBinding StartAngle}"
                    Stretch="None" />

            <ed:Arc x:Name="NumberPath" Margin="20" ArcThickness="0" ArcThicknessUnit="Pixel"
                    EndAngle="{TemplateBinding EndAngle}"
                    StartAngle="{TemplateBinding StartAngle}"
                    Stretch="None" />

            <ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" />
        </Grid>
    </ControlTemplate>

    <Style TargetType="{x:Type local:Dashboard}">
        <Setter Property="StartAngle" Value="-130" />
        <Setter Property="EndAngle" Value="130" />
        <Setter Property="FontSize" Value="12" />
        <Setter Property="Foreground" Value="#FFFFFF" />
        <Setter Property="Template" Value="{StaticResource Speed}" />
        <Setter Property="ContentTemplate" Value="{StaticResource DefaultLabelPanel}" />
        <Style.Triggers>
            <Trigger Property="Skin" Value="Flow">
                <Setter Property="StartAngle" Value="-120" />
                <Setter Property="EndAngle" Value="120" />
                <Setter Property="Foreground" Value="#929093" />
                <Setter Property="BorderBrush" Value="#746E7A" />
                <Setter Property="ShortTicksBrush" Value="#746E7A" />
                <Setter Property="LongTicksBrush" Value="#746E7A" />
                <Setter Property="Template" Value="{StaticResource Flow}" />
            </Trigger>
        </Style.Triggers>
    </Style>
</ResourceDictionary>

Dashboard.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Expression.Shapes;

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

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

        #region 依赖属性

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

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

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

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

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

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

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

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

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

        /// <summary>
        /// 获取或设置当前值
        /// </summary>
        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(5));

        /// <summary>
        /// 获取或设置长刻度个数,用于设置刻度盘显示几个长刻度
        /// </summary>
        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));

        /// <summary>
        /// 获取或设置两个长刻度之间的短刻度的个数
        /// </summary>
        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))));

        /// <summary>
        /// 刻度改变时的动画显示时长
        /// </summary>
        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));

        /// <summary>
        /// 刻度盘样式
        /// </summary>
        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));

        /// <summary>
        /// 短刻度颜色
        /// </summary>
        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));

        /// <summary>
        /// 长刻度颜色
        /// </summary>
        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 刻度盘当前值所对应的角度
        /// <summary>
        /// 刻度盘当前值所对应的角度依赖属性
        /// </summary>
        public static readonly DependencyProperty AngleProperty =
            DependencyProperty.Register(
                "Angle",
                typeof(double),
                typeof(Dashboard),
                new PropertyMetadata(0d));

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

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

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

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

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

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

        /// <summary>
        /// 获取或设置长刻度线,用于绑定PathListBox的ItemsSource
        /// </summary>
        /// <value>长刻度线.</value>
        public IList<object> NumberList
        {
            get { return (IList<object>)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方法
        /// <summary>
        /// 设置刻度线
        /// </summary>
        private void SetTicks()
        {
            List<object> numbers = new List<object>();
            List<object> shortticks = new List<object>();
            List<object> longticks = new List<object>();

            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;
        }

        /// <summary>
        /// 根据当前值设置圆弧的EndAngle
        /// </summary>
        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;
        }

        /// <summary>
        /// 角度值变化动画
        /// </summary>
        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
    }
}

再添加一个ControlEnum类文件:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WPF0317a
{
    #region DashboardSkinEnum
    /// <summary>
    /// 仪表盘类型
    /// </summary>
    public enum DashboardSkinEnum
    {
        /// <summary>
        /// 速度
        /// </summary>
        Speed,
        /// <summary>
        /// 流量
        /// </summary>
        Flow,
    }
    #endregion

    #region ProgressBarSkinEnum
    /// <summary>
    /// 进度条类型
    /// </summary>
    public enum ProgressBarSkinEnum
    {
        /// <summary>
        /// 方形进度条
        /// </summary>
        Rectangle,
        /// <summary>
        /// 环形进度条
        /// </summary>
        Circle,
    }
    #endregion

    #region EnumPlacement
    public enum EnumPlacement
    {
        /// <summary>
        /// 左上
        /// </summary>
        LeftTop,
        /// <summary>
        /// 左中
        /// </summary>
        LeftCenter,
        /// <summary>
        /// 左下
        /// </summary>
        LeftBottom,
        /// <summary>
        /// 右上
        /// </summary>
        RightTop,
        /// <summary>
        /// 右中
        /// </summary>
        RightCenter,
        /// <summary>
        /// 右下
        /// </summary>
        RightBottom,
        /// <summary>
        /// 上左
        /// </summary>
        TopLeft,
        /// <summary>
        /// 上中
        /// </summary>
        TopCenter,
        /// <summary>
        /// 上右
        /// </summary>
        TopRight,
        /// <summary>
        /// 下左
        /// </summary>
        BottomLeft,
        /// <summary>
        /// 下中
        /// </summary>
        BottomCenter,
        /// <summary>
        /// 下右
        /// </summary>
        BottomRight,
    }
    #endregion

    #region PlacementDirection
    public enum EnumPlacementDirection
    {
        Left,
        Top,
        Right,
        Bottom,
    }
    #endregion

    #region EnumPromptType
    /// <summary>
    /// 提示类型
    /// </summary>
    public enum EnumPromptType
    {
        /// <summary>
        /// 消息
        /// </summary>
        Info,
        /// <summary>
        /// 警告
        /// </summary>
        Warn,
        /// <summary>
        /// 失败
        /// </summary>
        Error,
        /// <summary>
        /// 成功
        /// </summary>
        Success,
    }
    #endregion

    #region EnumCompare
    public enum EnumCompare
    {
        /// <summary>
        /// 小于
        /// </summary>
        Less,
        /// <summary>
        /// 等于
        /// </summary>
        Equal,
        /// <summary>
        /// 大于
        /// </summary>
        Large,
        None,
    }
    #endregion

    #region EnumLoadingType
    public enum EnumLoadingType
    {
        /// <summary>
        /// 两个环形
        /// </summary>
        DoubleArc,
        /// <summary>
        /// 两个圆
        /// </summary>
        DoubleRound,
        /// <summary>
        /// 一个圆
        /// </summary>
        SingleRound,
        /// <summary>
        /// 仿Win10加载条
        /// </summary>
        Win10,
        /// <summary>
        /// 仿Android加载条
        /// </summary>
        Android,
        /// <summary>
        /// 仿苹果加载条
        /// </summary>
        Apple,
        Cogs,
        Normal,
    }
    #endregion

    #region CloseBoxTypeEnum
    public enum CloseBoxTypeEnum
    {
        /// <summary>
        /// 关闭窗口
        /// </summary>
        Close,
        /// <summary>
        /// 隐藏窗口
        /// </summary>
        Hide,
    }
    #endregion

    #region FlatButtonSkinEnum
    /// <summary>
    /// Button类型
    /// </summary>
    public enum FlatButtonSkinEnum
    {
        Yes,
        No,
        Default,
        primary,
        ghost,
        dashed,
        text,
        info,
        success,
        error,
        warning,
    }
    #endregion

    #region EnumTrigger
    public enum EnumTrigger
    {
        /// <summary>
        /// 悬浮
        /// </summary>
        Hover,
        /// <summary>
        /// 点击
        /// </summary>
        Click,
        /// <summary>
        /// 自定义
        /// </summary>
        Custom,
    }
    #endregion

    #region EnumTabControlType
    public enum EnumTabControlType
    {
        Line,
        Card,
    }
    #endregion

    #region IconType
    public enum EnumIconType
    {
        Info,
        Error,
        Warning,
        Success,
        MacOS,
        Windows,
        Linux,
        Android,
        Star_Empty,
        Star_Half,
        Star_Full,
    }
    #endregion

    #region EnumDatePickerType
    public enum EnumDatePickerType
    {
        /// <summary>
        /// 单个日期
        /// </summary>
        SingleDate,
        /// <summary>
        /// 连续的多个日期
        /// </summary>
        SingleDateRange,
        /// <summary>
        /// 只显示年份
        /// </summary>
        Year,
        /// <summary>
        /// 只显示月份
        /// </summary>
        Month,
        /// <summary>
        /// 显示一个日期和时间
        /// </summary>
        DateTime,
        /// <summary>
        /// 显示连续的日期和时间
        /// </summary>
        DateTimeRange,
    }
    #endregion

    #region DayTitle
    public enum DayTitle
    {= 0,,,,,,,
    }
    #endregion

    #region EnumPlayState 音视频播放状态枚举
    public enum EnumPlayState
    {
        /// <summary>
        /// 播放
        /// </summary>
        Play,
        /// <summary>
        /// 暂停
        /// </summary>
        Pause,
        /// <summary>
        /// 停止
        /// </summary>
        Stop,
    }
    #endregion

    #region EnumHeadingType 标题类型
    public enum EnumHeadingType
    {
        H1,
        H2,
        H3,
        H4,
        H5,
        H6,
    }
    #endregion

    #region EnumPatternType 正则类型
    /// <summary>
    /// 正则类型枚举
    /// </summary>
    public enum EnumPatternType
    {
        None,
        /// <summary>
        /// 不为空
        /// </summary>
        NotEmpty,
        /// <summary>
        /// 数字
        /// </summary>
        OnlyNumber,
        /// <summary>
        /// IP地址
        /// </summary>
        IPV4,
        /// <summary>
        /// IP地址
        /// </summary>
        IPV6,
        /// <summary>
        /// 邮箱
        /// </summary>
        Email,
        /// <summary>
        /// 15位身份证
        /// </summary>
        IdCard15,
        /// <summary>
        /// 18位身份证
        /// </summary>
        IdCard18,
        /// <summary>
        /// 手机号
        /// </summary>
        MobilePhone,
        /// <summary>
        /// 座机、固话
        /// </summary>
        Telephone,
        /// <summary>
        /// 只能录入中文
        /// </summary>
        OnlyChinese,
    }
    #endregion

    #region EnumValidateTrigger 校验模式
    /// <summary>
    /// 校验模式
    /// </summary>
    public enum EnumValidateTrigger
    {
        /// <summary>
        /// 属性值改变时触发
        /// </summary>
        PropertyChanged,
        /// <summary>
        /// 控件失去焦点时触发
        /// </summary>
        LostFocus,
    }
    #endregion

    #region EnumChooseBoxType
    public enum EnumChooseBoxType
    {
        /// <summary>
        /// 单文件
        /// </summary>
        SingleFile,
        /// <summary>
        /// 多文件
        /// </summary>
        MultiFile,
        /// <summary>
        /// 文件夹
        /// </summary>
        Folder,
    }
    #endregion
}

新建一个文件夹Converters,在里面添加一个转换器类WordAngleConverter:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;

namespace WPF0317a.Converters
{
    public class WordAngleConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string selected = "00";
            int hour = 0;

            if (int.TryParse(System.Convert.ToString(value), out hour))
            {
                if (hour < 10)
                {
                    selected = "0" + hour;
                }
                else
                {
                    selected = System.Convert.ToString(hour);
                }
            }

            return selected;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return null;
        }
    }
}

二.主窗体界面,Xaml文件代码:

<Window x:Class="WPF0317a.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPF0317a"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <StackPanel>
            <StackPanel Orientation="Horizontal">
                <StackPanel Orientation="Vertical">
                    <local:Dashboard x:Name="dashboard" Width="200" Height="200" Margin="10,20"
                               LongTickCount="5" Maximum="100" ShortTickCount="2" Skin="Speed"
                               Value="{Binding Path=Value,
                                               ElementName=slider}" />
                    <Button x:Name="btnGetValue" Width="100" Height="25" VerticalAlignment="Top"
                        Click="btnGetValue_Click" Content="获取值" />
                    <Slider x:Name="slider" Width="300" VerticalAlignment="Bottom" IsMoveToPointEnabled="True"
                        Maximum="100" Minimum="0" Value="80" Margin="10" />
                </StackPanel>
                <StackPanel Orientation="Vertical" Margin="40,0,0,0">
                    <Border Background="#190E1C">
                        <local:Dashboard x:Name="dashboard1" Width="300" Height="300" Margin="30,30,30,10"
                                   LongTickCount="9" Maximum="2000" ShortTickCount="5" Skin="Flow"
                                   Value="{Binding Path=Value,
                                                   ElementName=slider1}">
                            <local:Dashboard.ContentTemplate>
                                <DataTemplate>
                                    <StackPanel Margin="0,110,0,0" HorizontalAlignment="Center" Orientation="Vertical">
                                        <TextBlock Margin="0,4" Text="DOWNLOAD" />
                                        <TextBlock Margin="0,4" HorizontalAlignment="Center" FontSize="26" Foreground="White"
                                           Text="{Binding Path=Value,
                                                          StringFormat={}{0:N0},
                                                          ElementName=dashboard1}" />
                                        <TextBlock Margin="0,4" HorizontalAlignment="Center" Text="Mbps" />
                                        <Border Margin="0,30,0,0" BorderBrush="#929093" BorderThickness="1" CornerRadius="12"
                                        Padding="0,3">
                                            <TextBlock HorizontalAlignment="Center" Text="RETRY" />
                                        </Border>
                                    </StackPanel>
                                </DataTemplate>
                            </local:Dashboard.ContentTemplate>
                        </local:Dashboard>
                    </Border>
                    <Slider x:Name="slider1" Width="300" VerticalAlignment="Bottom" IsMoveToPointEnabled="True"
                        Maximum="2000" Minimum="0" Value="1168" Margin="10" />
                </StackPanel>
            </StackPanel>
        </StackPanel>
    </Grid>
</Window>

主窗体后台代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPF0317a
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void btnGetValue_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show(this.dashboard.Value.ToString());
        }
    }
}

三.运行效果:
在这里插入图片描述
源代码库下载地址:https://download.csdn.net/download/qq_43024228/12251111

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值