1.控件部分代码
<UserControl x:Class="Zhaoxi.Controls.Instrument"
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:Zhaoxi.Controls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Ellipse Fill="{Binding PlateBackground,RelativeSource={RelativeSource AncestorType=UserControl,Mode=FindAncestor}}"
Name="backEllipse"/>
<Canvas Name="mainCanvas" Width="{Binding Width,ElementName=backEllipse}" Height="{Binding Height,ElementName=backEllipse}"/>
<Path Data="" Stroke="White" StrokeThickness="4" Name="circle" RenderTransformOrigin="0.5,0.5"
StrokeStartLineCap="Round" StrokeEndLineCap="Round"
Width="{Binding Width,ElementName=backEllipse}" Height="{Binding Height,ElementName=backEllipse}">
<Path.RenderTransform>
<RotateTransform Angle="-45"/>
</Path.RenderTransform>
</Path>
<Path Data="" Fill="Green" Name="pointer" RenderTransformOrigin="0.5,0.5"
Width="{Binding Width,ElementName=backEllipse}" Height="{Binding Height,ElementName=backEllipse}">
<Path.RenderTransform>
<RotateTransform Angle="-45" x:Name="rtPointer"/>
</Path.RenderTransform>
</Path>
<Border Width="20" Height="20" CornerRadius="10">
<Border.Background>
<RadialGradientBrush>
<GradientStop Color="White" Offset="0.583"/>
<GradientStop Color="#FF97B5BD" Offset="1"/>
</RadialGradientBrush>
</Border.Background>
</Border>
</Grid>
</UserControl>
public partial class Instrument : UserControl
{
public Brush PlateBackground
{
get { return (Brush)GetValue(PlateBackgroundProperty); }
set { SetValue(PlateBackgroundProperty, value); }
}
public static readonly DependencyProperty PlateBackgroundProperty =
DependencyProperty.Register("PlateBackground", typeof(Brush), typeof(Instrument), new PropertyMetadata(default(Brush)));
public int Value
{
get { return (int)this.GetValue(ValueProperty); }
set { this.SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(int), typeof(Instrument),
new PropertyMetadata(default(int), new PropertyChangedCallback(OnPorpertyChanged)));
public int Minimum
{
get { return (int)GetValue(MinimumProperty); }
set { SetValue(MinimumProperty, value); }
}
public static readonly DependencyProperty MinimumProperty =
DependencyProperty.Register("Minimum", typeof(int), typeof(Instrument),
new PropertyMetadata(default(int), new PropertyChangedCallback(OnPorpertyChanged)));
public int Maximum
{
get { return (int)GetValue(MaximumProperty); }
set { SetValue(MaximumProperty, value); }
}
public static readonly DependencyProperty MaximumProperty =
DependencyProperty.Register("Maximum", typeof(int), typeof(Instrument),
new PropertyMetadata(default(int), new PropertyChangedCallback(OnPorpertyChanged)));
public int Interval
{
get { return (int)GetValue(IntervalProperty); }
set { SetValue(IntervalProperty, value); }
}
public static readonly DependencyProperty IntervalProperty =
DependencyProperty.Register("Interval", typeof(int), typeof(Instrument),
new PropertyMetadata(default(int), new PropertyChangedCallback(OnPorpertyChanged)));
public int ScaleTextSize
{
get { return (int)GetValue(ScaleTextSizeProperty); }
set { SetValue(ScaleTextSizeProperty, value); }
}
public static readonly DependencyProperty ScaleTextSizeProperty =
DependencyProperty.Register("ScaleTextSize", typeof(int), typeof(Instrument),
new PropertyMetadata(default(int), new PropertyChangedCallback(OnPorpertyChanged)));
public Brush ScaleBrush
{
get { return (Brush)GetValue(ScaleBrushProperty); }
set { SetValue(ScaleBrushProperty, value); }
}
public static readonly DependencyProperty ScaleBrushProperty =
DependencyProperty.Register("ScaleBrush", typeof(Brush), typeof(Instrument),
new PropertyMetadata(default(Brush), new PropertyChangedCallback(OnPorpertyChanged)));
public static void OnPorpertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as Instrument).Refresh();
}
public Instrument()
{
InitializeComponent();
this.SizeChanged += Instrument_SizeChanged;
}
private void Instrument_SizeChanged(object sender, SizeChangedEventArgs e)
{
double minSize = Math.Min(this.RenderSize.Width, this.RenderSize.Height);
this.backEllipse.Width = minSize;
this.backEllipse.Height = minSize;
}
private void Refresh()
{
double radius = this.backEllipse.Width / 2;
if (double.IsNaN(radius)) return;
this.mainCanvas.Children.Clear();
double step = 270.0 / (this.Maximum - this.Minimum);
for (int i = 0; i < this.Maximum - this.Minimum; i++)
{
Line lineScale = new Line();
lineScale.X1 = radius - (radius - 13) * Math.Cos((i * step - 45) * Math.PI / 180);
lineScale.Y1 = radius - (radius - 13) * Math.Sin((i * step - 45) * Math.PI / 180);
lineScale.X2 = radius - (radius - 8) * Math.Cos((i * step - 45) * Math.PI / 180);
lineScale.Y2 = radius - (radius - 8) * Math.Sin((i * step - 45) * Math.PI / 180);
lineScale.Stroke = this.ScaleBrush;
lineScale.StrokeThickness = 1;
this.mainCanvas.Children.Add(lineScale);
}
step = 270.0 / Interval;
int scaleText = this.Minimum;
for (int i = 0; i <= Interval; i++)
{
Line lineScale = new Line();
lineScale.X1 = radius - (radius - 20) * Math.Cos((i * step - 45) * Math.PI / 180);
lineScale.Y1 = radius - (radius - 20) * Math.Sin((i * step - 45) * Math.PI / 180);
lineScale.X2 = radius - (radius - 8) * Math.Cos((i * step - 45) * Math.PI / 180);
lineScale.Y2 = radius - (radius - 8) * Math.Sin((i * step - 45) * Math.PI / 180);
lineScale.Stroke = this.ScaleBrush;
lineScale.StrokeThickness = 1;
this.mainCanvas.Children.Add(lineScale);
TextBlock textScale = new TextBlock();
textScale.Width = 34;
textScale.TextAlignment = TextAlignment.Center;
textScale.FontSize = this.ScaleTextSize;
textScale.Text = (scaleText + (this.Maximum - this.Minimum) / Interval * i).ToString();
textScale.Foreground = this.ScaleBrush;
Canvas.SetLeft(textScale, radius - (radius - 36) * Math.Cos((i * step - 45) * Math.PI / 180) - 17);
Canvas.SetTop(textScale, radius - (radius - 36) * Math.Sin((i * step - 45) * Math.PI / 180) - 10);
this.mainCanvas.Children.Add(textScale);
}
string sData = "M{0} {1} A{0} {0} 0 1 1 {1} {2}";
sData = string.Format(sData, radius / 2, radius, radius * 1.5);
var converter = TypeDescriptor.GetConverter(typeof(Geometry));
this.circle.Data = (Geometry)converter.ConvertFrom(sData);
step = 270.0 / (this.Maximum - this.Minimum);
DoubleAnimation da = new DoubleAnimation((int)((this.Value - this.Minimum) * step) - 45, new Duration(TimeSpan.FromMilliseconds(200)));
this.rtPointer.BeginAnimation(RotateTransform.AngleProperty, da);
sData = "M{0} {1},{1} {2},{1} {3}";
sData = string.Format(sData, radius * 0.3, radius, radius - 5, radius + 5);
this.pointer.Data = (Geometry)converter.ConvertFrom(sData);
}
}
2.使用部分代码
xmlns:zxc="clr-namespace:xxx.Controls;assembly=xxx.Controls"
<zxc:Instrument Margin="0,20,0,40"
PlateBackground="Orange"
Value="{Binding InstrumentValue}"
Minimum="-10"
Maximum="90"
Interval="10"
ScaleTextSize="12"
ScaleBrush="White"/>