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