1,效果:
2,代码:
2.1,资源字典:BaseStyle.xaml
XML
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!--外轮廓颜色-->
<SolidColorBrush x:Key="ColorBrush">
<SolidColorBrush.Color>#190E1C</SolidColorBrush.Color>
</SolidColorBrush>
<!--外轮廓进度颜色-->
<SolidColorBrush x:Key="ColorBrush1" Color="#2B1A51"></SolidColorBrush>
<!--中心圆盘颜色-->
<Color x:Key="ColorLight2" >#23153B</Color>
<Color x:Key="ColorLight1">#23153B</Color>
<Color x:Key="ColorLight">#45246B </Color>
<!--指针颜色-->
<Color x:Key="LightBlueColor1">#00C9FF</Color >
<Color x:Key="LightBlueColor2">#00C9FF</Color>
<Color x:Key="LightBlueColor3">#00C9F0</Color>
</ResourceDictionary>
2.2,自定义圆弧类Arc
cs
//WPF未提供圆弧Shape,故根据Ellipse实现过程自定义一个圆弧类
class Arc : Shape
{
private Rect _rect = Rect.Empty;
public double StartAngle
{
get { return (double)GetValue(StartAngleProperty); }
set { SetValue(StartAngleProperty, value); }
}
// Using a DependencyProperty as the backing store for StartAngle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StartAngleProperty =
DependencyProperty.Register("StartAngle", typeof(double), typeof(Arc), new FrameworkPropertyMetadata((double)-135, FrameworkPropertyMetadataOptions.AffectsRender));
public double EndAngle
{
get { return (double)GetValue(EndAngleProperty); }
set { SetValue(EndAngleProperty, value); }
}
// Using a DependencyProperty as the backing store for EndAngle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty EndAngleProperty =
DependencyProperty.Register("EndAngle", typeof(double), typeof(Arc), new FrameworkPropertyMetadata((double)135, FrameworkPropertyMetadataOptions.AffectsRender));
public double ArcThickness
{
get { return (double)GetValue(ArcThicknessProperty); }
set { SetValue(ArcThicknessProperty, value); }
}
// Using a DependencyProperty as the backing store for ArcThickness. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ArcThicknessProperty =
DependencyProperty.Register("ArcThickness", typeof(double), typeof(Arc), new FrameworkPropertyMetadata((double)10, FrameworkPropertyMetadataOptions.AffectsRender));
public override Geometry RenderedGeometry => DefiningGeometry;
public override Transform GeometryTransform => Transform.Identity;
protected override Geometry DefiningGeometry
{
get
{
if (_rect.IsEmpty)
{
return Geometry.Empty;
}
PathGeometry path = new PathGeometry();
PathFigure figure = new PathFigure();
figure.IsClosed = false;
//根据起始角度算出起始点
//可绘图的区域为_rec
double offsetAngle = 270;
double diameter = _rect.Width > _rect.Height ? _rect.Height : _rect.Width;
Point centerPoint = new Point(_rect.X + _rect.Width / 2, _rect.Y + _rect.Height / 2);
double xoffset = diameter * Math.Cos((StartAngle + offsetAngle) / 180 * Math.PI) / 2;
double yoffset = diameter * Math.Sin((StartAngle + offsetAngle) / 180 * Math.PI) / 2;
Point startPoint = new Point(centerPoint.X + xoffset, centerPoint.Y + yoffset);
double xoffset2 = diameter * Math.Cos((EndAngle + offsetAngle) / 180 * Math.PI) / 2;
double yoffset2 = diameter * Math.Sin((EndAngle + offsetAngle) / 180 * Math.PI) / 2;
Point endPoint = new Point(centerPoint.X + xoffset2, centerPoint.Y + yoffset2);
figure.StartPoint = startPoint;
ArcSegment arc = new ArcSegment
{
Point = endPoint,
Size = new Size(diameter / 2, diameter / 2),
SweepDirection = SweepDirection.Clockwise
};
if (EndAngle - StartAngle < 180)
{
arc.IsLargeArc = false;
}
else
{
arc.IsLargeArc = true;
}
figure.Segments.Add(arc);
path.Figures.Add(figure);
return path;
}
}
static Arc()
{
Shape.StretchProperty.OverrideMetadata(typeof(Arc), new FrameworkPropertyMetadata(Stretch.Fill));
}
protected override Size MeasureOverride(Size constraint)
{
double width = constraint.Width;
double height = constraint.Height;
if (double.IsInfinity(width) && double.IsInfinity(height))
{
return GetNaturalSize();
}
if (base.Stretch == Stretch.UniformToFill)
{
width = ((!double.IsInfinity(width) && !double.IsInfinity(height)) ? Math.Max(width, height) : Math.Min(width, height));
return new Size(width, width);
}
return constraint;
}
protected override Size ArrangeOverride(Size finalSize)
{
double strokeThickness = ArcThickness;
double num = strokeThickness / 2.0;
_rect = new Rect(num, num, Math.Max(0.0, finalSize.Width - strokeThickness), Math.Max(0.0, finalSize.Height - strokeThickness));
switch (base.Stretch)
{
case Stretch.None:
{
ref Rect rect = ref _rect;
double width = (_rect.Height = 0.0);
rect.Width = width;
break;
}
case Stretch.Uniform:
if (_rect.Width > _rect.Height)
{
_rect.Width = _rect.Height;
}
else
{
_rect.Height = _rect.Width;
}
break;
case Stretch.UniformToFill:
if (_rect.Width < _rect.Height)
{
_rect.Width = _rect.Height;
}
else
{
_rect.Height = _rect.Width;
}
break;
}
return finalSize;
// return base.ArrangeOverride(finalSize);
}
protected override void OnRender(DrawingContext drawingContext)
{
if (!_rect.IsEmpty)
{
Pen pen = new Pen();
pen.Brush = Stroke;
pen.Thickness = ArcThickness;
pen.StartLineCap = StrokeStartLineCap;
pen.EndLineCap = StrokeEndLineCap;
drawingContext.DrawGeometry(base.Fill, pen, RenderedGeometry);
}
}
Size GetNaturalSize()
{
double strokeThickness = GetStrokeThickness();
return new Size(strokeThickness * 2, strokeThickness * 2);
}
double GetStrokeThickness()
{
if (double.IsNaN(ArcThickness) || double.IsInfinity(ArcThickness))
{
return 0.0;
}
else
{
return ArcThickness;
}
}
}
2.3,自定义仪表控件xaml
cs
<UserControl x:Class="MyWpfControlLibrary.MeterPlate"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MyWpfControlLibrary"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="400" x:Name="meterPlate">
<UserControl.Resources>
<ResourceDictionary Source="pack://application:,,,/MyWpfControlLibrary;component/basestyle.xaml"></ResourceDictionary>
</UserControl.Resources>
<Viewbox>
<Grid>
<Border x:Name="border01" Background="{Binding ElementName=meterPlate, Path=PlateBackground}" CornerRadius="200" BorderThickness="{Binding ElementName=meterPlate, Path=PlateBorderThickness}" BorderBrush="{Binding ElementName=meterPlate, Path=PlateBorderBrush}" ClipToBounds="True" >
<Grid>
<Canvas Name="canvasPlate" Width="400" Height="400" Background="Transparent" >
</Canvas>
<local:Arc x:Name="arc01" Opacity="0.3" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StartAngle="{Binding ElementName=meterPlate, Path=StartAngle}" EndAngle="{Binding ElementName=meterPlate, Path=EndAngle}" Stroke="{DynamicResource ColorBrush}" ArcThickness="{Binding ElementName=meterPlate, Path=ArcThickness}" ></local:Arc>
<local:Arc ArcThickness="{Binding ElementName=meterPlate, Path=ArcThickness}" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StartAngle="{Binding ElementName=meterPlate, Path=StartAngle}" Opacity="0.8" x:Name="arckd" EndAngle="110" Stroke="{DynamicResource ColorBrush1}"></local:Arc>
<Border Width="200" Height="200" CornerRadius="100" Opacity="0.5" >
<Border.Background>
<RadialGradientBrush RadiusX="1" RadiusY="1">
<GradientStop Color="{DynamicResource ColorLight2}" Offset="0.3"></GradientStop>
<GradientStop Color="{DynamicResource ColorLight1}" Offset="0.4"></GradientStop>
<GradientStop Color="{DynamicResource ColorLight}" Offset="1"></GradientStop>
</RadialGradientBrush>
</Border.Background>
</Border>
<Path HorizontalAlignment="Center" VerticalAlignment="Center" Data="M0 -5,160 0,0 5 z" RenderTransformOrigin="0.5,0.5" Margin="14">
<Path.Fill>
<RadialGradientBrush RadiusX="1" RadiusY="1">
<GradientStop Color="{DynamicResource LightBlueColor1}" Offset="0.3"/>
<GradientStop Color="{DynamicResource LightBlueColor2}" Offset="0.4"/>
<GradientStop Color="{DynamicResource LightBlueColor3}" Offset="1"/>
</RadialGradientBrush>
</Path.Fill>
<Path.RenderTransform>
<TransformGroup>
<TranslateTransform X="80"></TranslateTransform>
<RotateTransform x:Name="rtPointer" />
</TransformGroup>
</Path.RenderTransform>
</Path>
<Border Width="100" Height="100" CornerRadius="50" Margin="14">
<Border.Background>
<RadialGradientBrush RadiusX="1" RadiusY="1">
<GradientStop Color="{DynamicResource ColorLight}" Offset="0.5"/>
<GradientStop Color="{DynamicResource ColorLight1}" Offset="0.3"/>
<GradientStop Color="{DynamicResource ColorLight2}" Offset="0.1"/>
</RadialGradientBrush>
</Border.Background>
<StackPanel Panel.ZIndex="999" Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock x:Name="txtCurValue" Foreground="White" Text="{Binding ElementName=meterPlate, Path=Value}" FontSize="30" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock Foreground="White" Text="km/h" FontSize="12" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</StackPanel>
</Border>
</Grid>
</Border>
</Grid>
</Viewbox>
</UserControl>
效果:
2.4,仪表控件代码:
cs
public partial class MeterPlate : UserControl
{
const double OffsetAngle = 270;
public static readonly DependencyProperty StartAngleProperty;
public static readonly DependencyProperty EndAngleProperty;
public static readonly DependencyProperty ValueProperty;
public static readonly DependencyProperty MinNumProperty;
public static readonly DependencyProperty MaxNumProperty;
public static readonly DependencyProperty PlateBackgroundProperty;
public static readonly DependencyProperty PlateBorderBrushProperty;
public static readonly DependencyProperty PlateBorderThicknessProperty;
public static readonly DependencyProperty ArcThicknessProperty;
public static readonly DependencyProperty LowAlarmPercentProperty;
public static readonly DependencyProperty HeightAlarmPercentProperty;
public static readonly DependencyProperty LowAlarmColorProperty;
public static readonly DependencyProperty HeightAlarmColorProperty;
public MeterPlate()
{
InitializeComponent();
}
static MeterPlate()
{
StartAngleProperty =
DependencyProperty.Register("StartAngle", typeof(double), typeof(MeterPlate), new FrameworkPropertyMetadata((double)-135, FrameworkPropertyMetadataOptions.AffectsRender));
EndAngleProperty =
DependencyProperty.Register("EndAngle", typeof(double), typeof(MeterPlate), new FrameworkPropertyMetadata((double)135, FrameworkPropertyMetadataOptions.AffectsRender));
ValueProperty =
DependencyProperty.Register("Value", typeof(double), typeof(MeterPlate),
new FrameworkPropertyMetadata((double)45, FrameworkPropertyMetadataOptions.AffectsRender));
MinNumProperty =
DependencyProperty.Register("MinNum", typeof(double), typeof(MeterPlate),
new FrameworkPropertyMetadata((double)0, FrameworkPropertyMetadataOptions.AffectsRender));
MaxNumProperty =
DependencyProperty.Register("MaxNum", typeof(double), typeof(MeterPlate),
new FrameworkPropertyMetadata((double)120, FrameworkPropertyMetadataOptions.AffectsRender));
PlateBackgroundProperty =
DependencyProperty.Register("PlateBackground", typeof(Brush), typeof(MeterPlate), new PropertyMetadata(new SolidColorBrush(Color.FromRgb(43, 26, 81))));
PlateBorderBrushProperty =
DependencyProperty.Register("PlateBorderBrush", typeof(Brush), typeof(MeterPlate), null);
PlateBorderThicknessProperty =
DependencyProperty.Register("PlateBorderThickness", typeof(Thickness), typeof(MeterPlate), new PropertyMetadata(new Thickness(0)));
ArcThicknessProperty =
DependencyProperty.Register("ArcThickness", typeof(double), typeof(MeterPlate), new PropertyMetadata((double)30));
LowAlarmPercentProperty =
DependencyProperty.Register("LowAlarmPercent", typeof(double), typeof(MeterPlate), new FrameworkPropertyMetadata((double)1, FrameworkPropertyMetadataOptions.AffectsRender));
HeightAlarmPercentProperty =
DependencyProperty.Register(" HeightAlarmPercent", typeof(double), typeof(MeterPlate), new FrameworkPropertyMetadata((double)1, FrameworkPropertyMetadataOptions.AffectsRender));
LowAlarmColorProperty =
DependencyProperty.Register("LowAlarmColor", typeof(Color), typeof(MeterPlate), new FrameworkPropertyMetadata(Colors.Orange, FrameworkPropertyMetadataOptions.AffectsRender));
HeightAlarmColorProperty =
DependencyProperty.Register("HeightAlarmColor", typeof(Color), typeof(MeterPlate), new FrameworkPropertyMetadata(Colors.Red, FrameworkPropertyMetadataOptions.AffectsRender));
}
[Browsable(true), Category("自定义属性"), Description("仪表盘开始角度")]
public double StartAngle
{
get { return (double)GetValue(StartAngleProperty); }
set { SetValue(StartAngleProperty, value); }
}
[Browsable(true), Category("自定义属性"), Description("仪表盘结束角度")]
public double EndAngle
{
get { return (double)GetValue(EndAngleProperty); }
set { SetValue(EndAngleProperty, value); }
}
[Browsable(true), Category("自定义属性"), Description("当前值")]
public double Value
{
get { return (double)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
[Browsable(true), Category("自定义属性"), Description("仪表盘最小值")]
public double MinNum
{
get { return (double)GetValue(MinNumProperty); }
set { SetValue(MinNumProperty, value); }
}
[Browsable(true), Category("自定义属性"), Description("仪表盘最大值")]
public double MaxNum
{
get { return (double)GetValue(MaxNumProperty); }
set { SetValue(MaxNumProperty, value); }
}
[Browsable(true), Category("自定义属性"), Description("仪表盘低值区域所占区域默认为1")]
public double LowAlarmPercent
{
get { return (double)GetValue(LowAlarmPercentProperty); }
set { SetValue(LowAlarmPercentProperty, value); }
}
[Browsable(true), Category("自定义属性"), Description("仪表盘高值区域所占区域默认为1")]
public double HeightAlarmPercent
{
get { return (double)GetValue(HeightAlarmPercentProperty); }
set { SetValue(HeightAlarmPercentProperty, value); }
}
[Browsable(true), Category("自定义属性"), Description("仪表盘低值区域刻度值与刻度线颜色")]
public Color LowAlarmColor
{
get { return (Color)GetValue(LowAlarmColorProperty); }
set { SetValue(LowAlarmColorProperty, value); }
}
[Browsable(true), Category("自定义属性"), Description("仪表盘高值区域刻度值与刻度线颜色")]
public Color HeightAlarmColor
{
get { return (Color)GetValue(HeightAlarmColorProperty); }
set { SetValue(HeightAlarmColorProperty, value); }
}
[Browsable(true), Category("自定义属性"), Description("仪表盘背景画刷")]
public Brush PlateBackground
{
get { return (Brush)GetValue(PlateBackgroundProperty); }
set { SetValue(PlateBackgroundProperty, value); }
}
[Browsable(true), Category("自定义属性"), Description("仪表盘边框画刷")]
public Brush PlateBorderBrush
{
get { return (Brush)GetValue(PlateBorderBrushProperty); }
set { SetValue(PlateBorderBrushProperty, value); }
}
[Browsable(true), Category("自定义属性"), Description("仪表盘边框宽度")]
public Thickness PlateBorderThickness
{
get { return (Thickness)GetValue(PlateBorderThicknessProperty); }
set { SetValue(PlateBorderThicknessProperty, value); }
}
[Browsable(true), Category("自定义属性"), Description("仪表盘进度条宽度")]
public double ArcThickness
{
get { return (double)GetValue(ArcThicknessProperty); }
set { SetValue(ArcThicknessProperty, value); }
}
protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);
DrawScale();
DrawAngle();
}
/// <summary>
/// 画表盘的刻度
/// </summary>
private void DrawScale()
{
double unitAngle = (EndAngle - StartAngle) / (MaxNum - MinNum);
double realStartAngle = StartAngle + OffsetAngle;
double outgap = arc01.ArcThickness;
this.canvasPlate.Children.Clear();
Point centerPoint = new Point(200, 200);
if (!double.IsInfinity(border01.BorderThickness.Left) && !double.IsNaN(border01.BorderThickness.Left))
{
centerPoint = new Point(200 - border01.BorderThickness.Left, 200 - border01.BorderThickness.Left);
}
for (double i = 0; i <= this.MaxNum - this.MinNum; i++)
{
//添加刻度线
Line lineScale = new Line();
if (LowAlarmPercent != 0 && i <= LowAlarmPercent * 10)
{
lineScale.Stroke = new SolidColorBrush(LowAlarmColor);
}
else if (HeightAlarmPercent != 0 && i >= (MaxNum - HeightAlarmPercent * 10))
{
lineScale.Stroke = new SolidColorBrush(HeightAlarmColor);
}
else
{
lineScale.Stroke = new SolidColorBrush(Colors.White);
if (i % 10 != 0)
{
lineScale.Opacity = 0.6;
}
}
if (i % 10 == 0)
{
//注意Math.Cos和Math.Sin的参数是弧度,记得将角度转为弧度制
lineScale.X1 = centerPoint.X + (centerPoint.X - outgap - 20) * Math.Cos((i * unitAngle + realStartAngle) * Math.PI / 180);
lineScale.Y1 = centerPoint.Y + (centerPoint.X - outgap - 20) * Math.Sin((i * unitAngle + realStartAngle) * Math.PI / 180);
lineScale.StrokeThickness = 2;
//添加刻度值
TextBlock txtScale = new TextBlock();
txtScale.Text = (i + this.MinNum).ToString();
txtScale.Width = 34;
txtScale.TextAlignment = TextAlignment.Center;
if (LowAlarmPercent != 0 && i <= LowAlarmPercent * 10)
{
txtScale.Foreground = new SolidColorBrush(LowAlarmColor);
}
else if (HeightAlarmPercent != 0 && i >= (MaxNum - HeightAlarmPercent * 10))
{
txtScale.Foreground = new SolidColorBrush(HeightAlarmColor);
}
else
{
txtScale.Foreground = new SolidColorBrush(Colors.White);
}
txtScale.RenderTransform = new RotateTransform() { Angle = 0, CenterX = 17, CenterY = 8 };
txtScale.FontSize = 18;
if (i > (MaxNum - MinNum) / 2)
{
Canvas.SetLeft(txtScale, centerPoint.X + (centerPoint.X - outgap - 35) * Math.Cos((i * unitAngle + realStartAngle) * Math.PI / 180) - 20);
Canvas.SetTop(txtScale, centerPoint.Y + (centerPoint.X - outgap - 35) * Math.Sin((i * unitAngle + realStartAngle) * Math.PI / 180) - 10);
}
else
{
Canvas.SetLeft(txtScale, centerPoint.X + (centerPoint.X - outgap - 35) * Math.Cos((i * unitAngle + realStartAngle) * Math.PI / 180) - 17);
Canvas.SetTop(txtScale, centerPoint.Y + (centerPoint.X - outgap - 35) * Math.Sin((i * unitAngle + realStartAngle) * Math.PI / 180) - 10);
}
this.canvasPlate.Children.Add(txtScale);
}
else
{
lineScale.X1 = centerPoint.X + (centerPoint.X - outgap - 10) * Math.Cos((i * unitAngle + realStartAngle) * Math.PI / 180);
lineScale.Y1 = centerPoint.Y + (centerPoint.X - outgap - 10) * Math.Sin((i * unitAngle + realStartAngle) * Math.PI / 180);
lineScale.StrokeThickness = 1;
// lineScale.Opacity = 0.6;
}
lineScale.X2 = centerPoint.X + (centerPoint.X - outgap) * Math.Cos((i * unitAngle + realStartAngle) * Math.PI / 180);
lineScale.Y2 = centerPoint.Y + (centerPoint.X - outgap) * Math.Sin((i * unitAngle + realStartAngle) * Math.PI / 180);
this.canvasPlate.Children.Add(lineScale);
}
if (LowAlarmPercent != 0 && Value <= LowAlarmPercent * 10)
{
txtCurValue.Foreground = new SolidColorBrush(LowAlarmColor);
}
else if (HeightAlarmPercent != 0 && Value >= (MaxNum - HeightAlarmPercent * 10))
{
txtCurValue.Foreground = new SolidColorBrush(HeightAlarmColor);
}
else
{
txtCurValue.Foreground = new SolidColorBrush(Colors.White);
}
}
private void DrawAngle()
{
double step = (Value - MinNum) / (this.MaxNum - this.MinNum) * (EndAngle - StartAngle) + OffsetAngle + StartAngle;
double desAngle = (Value - MinNum) / (this.MaxNum - this.MinNum) * (EndAngle - StartAngle) + StartAngle;
if (Value < MinNum)
{
step = OffsetAngle + StartAngle;
desAngle = StartAngle;
}
if (Value > MaxNum)
{
step = OffsetAngle + EndAngle;
desAngle = EndAngle;
}
DoubleAnimation da = new DoubleAnimation(step, new Duration(TimeSpan.FromMilliseconds(200)));
this.rtPointer.BeginAnimation(RotateTransform.AngleProperty, da);
//进度条显示
DoubleAnimation da2 = new DoubleAnimation(desAngle, new Duration(TimeSpan.FromMilliseconds(200)));
this.arckd.BeginAnimation(Arc.EndAngleProperty, da2);
}
}
3,应用:
XML
<Window x:Class="Demo.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:Demo"
mc:Ignorable="d"
xmlns:my="clr-namespace:MyWpfControlLibrary;assembly=MyWpfControlLibrary"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="300*"/>
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
<my:MeterPlate StartAngle="-135" PlateBackground="SlateBlue" LowAlarmPercent="2" HeightAlarmPercent="2" MaxNum="120" MinNum="0" EndAngle="135" Value="{Binding Value}" Margin="0,0,35,10" ></my:MeterPlate>
<Grid Grid.Column="1" Margin="10">
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button x:Name="btnStart" Margin="10" Content="开始" Click="btnStart_Click"></Button>
<TextBlock Grid.Row="1" Margin="10" Text="{Binding Value}" FontSize="16" FontWeight="Bold" TextAlignment="Center"></TextBlock>
</Grid>
</Grid>
</Window>
效果
测试代码:
cs
public partial class MainWindow : Window
{
public double Value
{
get { return (double)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
// Using a DependencyProperty as the backing store for Value. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(double), typeof(MainWindow), new PropertyMetadata((double)0
));
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
bool isBreak = false;
private void btnStart_Click(object sender, RoutedEventArgs e)
{
if (btnStart.Content.ToString().Equals("开始"))
{
isBreak = false;
DoWork();
}
else
{
isBreak = true;
}
}
Random random = new Random();
async void DoWork()
{
btnStart.Content = "运行中";
await Task.Run(() =>
{
while (true)
{
if (isBreak)
{
break;
}
Dispatcher.Invoke(() =>
{
Value+=random.Next(0,20);
if (Value >= 120)
{
Value = 0;
}
});
System.Threading.Thread.Sleep(500);
}
});
btnStart.Content = "停止";
await Task.Delay(2000);
btnStart.Content = "开始";
}
}