在我的自定义控件中再添加一些 属性
Add some more property to my custom control
所以我有这个 Gauge
:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controlsGauge="clr-namespace:MyApplication.Controllers">
Gauge.xaml
<Style TargetType="controlsGauge:Gauge">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controlsGauge:Gauge">
<Viewbox>
<Grid Height="200"
Width="200">
<!-- Ticks -->
<Line x:Name="TicksProxy"
Visibility="Collapsed"
Fill="{TemplateBinding TickBrush}" />
<ItemsControl ItemsSource="{TemplateBinding Ticks}"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Height="15"
Width="8"
Fill="{Binding Fill, ElementName=TicksProxy}">
<Rectangle.RenderTransform>
<TransformGroup>
<TranslateTransform X="-2.5"
Y="-95" />
<RotateTransform Angle="{Binding}" />
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- Scale -->
<Path Name="PART_Scale"
Stroke="{TemplateBinding ScaleBrush}"
StrokeThickness="{TemplateBinding ScaleWidth}" />
<!-- Trail -->
<Path Name="PART_Trail"
Stroke="{TemplateBinding TrailBrush}"
StrokeThickness="{TemplateBinding ScaleWidth}" />
<!-- Scale Ticks -->
<Line x:Name="ScaleTicksProxy"
Visibility="Collapsed"
Fill="{TemplateBinding ScaleTickBrush}"
X1="{TemplateBinding ScaleWidth}" />
<ItemsControl ItemsSource="{TemplateBinding Ticks}"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Height="{Binding X1, ElementName=ScaleTicksProxy}"
Width="2"
Fill="{Binding Fill, ElementName=ScaleTicksProxy}">
<Rectangle.RenderTransform>
<TransformGroup>
<TranslateTransform X="-0.5"
Y="-77" />
<RotateTransform Angle="{Binding}" />
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- Value and Unit -->
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,145,0,0">
<StackPanel.RenderTransform>
<RotateTransform Angle="0.5"/>
</StackPanel.RenderTransform>
<StackPanel Orientation="Horizontal">
<TextBlock Name="PART_ValueText"
Foreground="Orange"
FontSize="16"
FontFamily="Comic Sans MS"
FontWeight="SemiBold"
Text="{TemplateBinding Value}"
TextAlignment="Center"
Margin="0 0 0 0" />
<TextBlock Foreground="Orange"
FontSize="16"
FontFamily="Comic Sans MS"
FontWeight="SemiBold"
Text="%"
Margin="0 0 0 0" />
</StackPanel>
<TextBlock Foreground="{TemplateBinding UnitBrush}"
FontSize="16"
TextAlignment="Center"
Text="{TemplateBinding Unit}"
Margin="0" />
</StackPanel>
<!-- Needle -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- The RenderTransform is in code behind. -->
<Path Name="PART_Needle"
Stretch="Uniform"
HorizontalAlignment="Center"
Fill="{TemplateBinding NeedleBrush}"
Data="M 0,0 l 0,100 l 5,0 l 0,-100 l -5,0"
RenderTransformOrigin="0.5,1">
</Path>
</Grid>
</Grid>
</Viewbox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Gauge.cs
[TemplatePart(Name = NeedlePartName, Type = typeof(Path))]
[TemplatePart(Name = ScalePartName, Type = typeof(Path))]
[TemplatePart(Name = TrailPartName, Type = typeof(Path))]
[TemplatePart(Name = ValueTextPartName, Type = typeof(TextBlock))]
public class 仪表:UserControl
{
#region常量
private const string NeedlePartName = "PART_Needle";
private const string ScalePartName = "PART_Scale";
private const string TrailPartName = "PART_Trail";
private const string ValueTextPartName = "PART_ValueText";
private const double Degrees2Radians = Math.PI / 180;
#endregion Constants
#region Dependency Property Registrations
public static readonly DependencyProperty MinimumProperty =
DependencyProperty.Register("Minimum", typeof(double), typeof(Gauge), new PropertyMetadata(0.0));
public static readonly DependencyProperty MaximumProperty =
DependencyProperty.Register("Maximum", typeof(double), typeof(Gauge), new PropertyMetadata(100.0));
public static readonly DependencyProperty ScaleWidthProperty =
DependencyProperty.Register("ScaleWidth", typeof(Double), typeof(Gauge), new PropertyMetadata(26.0));
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(double), typeof(Gauge), new PropertyMetadata(0.0, OnValueChanged));
public static readonly DependencyProperty UnitProperty =
DependencyProperty.Register("Unit", typeof(string), typeof(Gauge), new PropertyMetadata(string.Empty));
public static readonly DependencyProperty NeedleBrushProperty =
DependencyProperty.Register("NeedleBrush", typeof(Brush), typeof(Gauge), new PropertyMetadata(new SolidColorBrush(Colors.OrangeRed)));
public static readonly DependencyProperty ScaleBrushProperty =
DependencyProperty.Register("ScaleBrush", typeof(Brush), typeof(Gauge), new PropertyMetadata(new SolidColorBrush(Colors.LightGray)));
public static readonly DependencyProperty TickBrushProperty =
DependencyProperty.Register("TickBrush", typeof(Brush), typeof(Gauge), new PropertyMetadata(new SolidColorBrush(Colors.DimGray)));
public static readonly DependencyProperty TrailBrushProperty =
DependencyProperty.Register("TrailBrush", typeof(Brush), typeof(Gauge), new PropertyMetadata(new SolidColorBrush(Colors.Orange)));
public static readonly DependencyProperty ValueBrushProperty =
DependencyProperty.Register("ValueBrush", typeof(Brush), typeof(Gauge), new PropertyMetadata(new SolidColorBrush(Colors.DimGray)));
public static readonly DependencyProperty ScaleTickBrushProperty =
DependencyProperty.Register("ScaleTickBrush", typeof(Brush), typeof(Gauge), new PropertyMetadata(new SolidColorBrush(Colors.White)));
public static readonly DependencyProperty UnitBrushProperty =
DependencyProperty.Register("UnitBrush", typeof(Brush), typeof(Gauge), new PropertyMetadata(new SolidColorBrush(Colors.DimGray)));
public static readonly DependencyProperty ValueStringFormatProperty =
DependencyProperty.Register("ValueStringFormat", typeof(string), typeof(Gauge), new PropertyMetadata("N0"));
protected static readonly DependencyProperty ValueAngleProperty =
DependencyProperty.Register("ValueAngle", typeof(double), typeof(Gauge), new PropertyMetadata(null));
public static readonly DependencyProperty TicksProperty =
DependencyProperty.Register("Ticks", typeof(IEnumerable<double>), typeof(Gauge), new PropertyMetadata(null));
#endregion Dependency Property Registrations
#region Constructors
public Gauge()
{
this.DefaultStyleKey = typeof(Gauge);
this.Ticks = this.getTicks();
}
#endregion Constructors
#region Properties
public double Minimum
{
get { return (double)GetValue(MinimumProperty); }
set { SetValue(MinimumProperty, value); }
}
public double Maximum
{
get { return (double)GetValue(MaximumProperty); }
set { SetValue(MaximumProperty, value); }
}
public Double ScaleWidth
{
get { return (Double)GetValue(ScaleWidthProperty); }
set { SetValue(ScaleWidthProperty, value); }
}
public double Value
{
get { return (double)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public string Unit
{
get { return (string)GetValue(UnitProperty); }
set { SetValue(UnitProperty, value); }
}
public Brush NeedleBrush
{
get { return (Brush)GetValue(NeedleBrushProperty); }
set { SetValue(NeedleBrushProperty, value); }
}
public Brush TrailBrush
{
get { return (Brush)GetValue(TrailBrushProperty); }
set { SetValue(TrailBrushProperty, value); }
}
public Brush ScaleBrush
{
get { return (Brush)GetValue(ScaleBrushProperty); }
set { SetValue(ScaleBrushProperty, value); }
}
public Brush ScaleTickBrush
{
get { return (Brush)GetValue(ScaleTickBrushProperty); }
set { SetValue(ScaleTickBrushProperty, value); }
}
public Brush TickBrush
{
get { return (Brush)GetValue(TickBrushProperty); }
set { SetValue(TickBrushProperty, value); }
}
public Brush ValueBrush
{
get { return (Brush)GetValue(ValueBrushProperty); }
set { SetValue(ValueBrushProperty, value); }
}
public Brush UnitBrush
{
get { return (Brush)GetValue(UnitBrushProperty); }
set { SetValue(UnitBrushProperty, value); }
}
public string ValueStringFormat
{
get { return (string)GetValue(ValueStringFormatProperty); }
set { SetValue(ValueStringFormatProperty, value); }
}
public double ValueAngle
{
get { return (double)GetValue(ValueAngleProperty); }
set { SetValue(ValueAngleProperty, value); }
}
public IEnumerable<double> Ticks
{
get { return (IEnumerable<double>)GetValue(TicksProperty); }
set { SetValue(TicksProperty, value); }
}
#endregion Properties
public override void OnApplyTemplate()
{
// Draw Scale
var scale = this.GetTemplateChild(ScalePartName) as Path;
if (scale != null)
{
var pg = new PathGeometry();
var pf = new PathFigure();
pf.IsClosed = false;
var middleOfScale = 77 - this.ScaleWidth / 2;
pf.StartPoint = this.ScalePoint(-150, middleOfScale);
var seg = new ArcSegment();
seg.SweepDirection = SweepDirection.Clockwise;
seg.IsLargeArc = true;
seg.Size = new Size(middleOfScale, middleOfScale);
seg.Point = this.ScalePoint(150, middleOfScale);
pf.Segments.Add(seg);
pg.Figures.Add(pf);
scale.Data = pg;
}
OnValueChanged(this, new DependencyPropertyChangedEventArgs());
base.OnApplyTemplate();
}
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Gauge c = (Gauge)d;
if (!Double.IsNaN(c.Value))
{
var middleOfScale = 77 - c.ScaleWidth / 2;
var needle = c.GetTemplateChild(NeedlePartName) as Path;
var valueText = c.GetTemplateChild(ValueTextPartName) as TextBlock;
c.ValueAngle = c.ValueToAngle(c.Value);
// Needle
if (needle != null)
{
needle.RenderTransform = new RotateTransform() { Angle = c.ValueAngle };
}
// Trail
var trail = c.GetTemplateChild(TrailPartName) as Path;
if (trail != null)
{
if (c.ValueAngle > -146)
{
trail.Visibility = Visibility.Visible;
var pg = new PathGeometry();
var pf = new PathFigure();
pf.IsClosed = false;
pf.StartPoint = c.ScalePoint(-150, middleOfScale);
var seg = new ArcSegment();
seg.SweepDirection = SweepDirection.Clockwise;
// We start from -150, so +30 becomes a large arc.
seg.IsLargeArc = c.ValueAngle > 30;
seg.Size = new Size(middleOfScale, middleOfScale);
seg.Point = c.ScalePoint(c.ValueAngle, middleOfScale);
pf.Segments.Add(seg);
pg.Figures.Add(pf);
trail.Data = pg;
}
else
{
trail.Visibility = Visibility.Collapsed;
}
}
// Value Text
if (valueText != null)
{
valueText.Text = c.Value.ToString(c.ValueStringFormat);
}
}
}
private Point ScalePoint(double angle, double middleOfScale)
{
return new Point(100 + Math.Sin(Degrees2Radians * angle) * middleOfScale, 100 - Math.Cos(Degrees2Radians * angle) * middleOfScale);
}
private double ValueToAngle(double value)
{
double minAngle = -150;
double maxAngle = 150;
// Off-scale to the left
if (value < this.Minimum)
{
return minAngle - 7.5;
}
// Off-scale to the right
if (value > this.Maximum)
{
return maxAngle + 7.5;
}
double angularRange = maxAngle - minAngle;
return (value - this.Minimum) / (this.Maximum - this.Minimum) * angularRange + minAngle;
}
private IEnumerable<double> getTicks()
{
double tickSpacing = (this.Maximum - this.Minimum) / 10;
for (double tick = this.Minimum; tick <= this.Maximum; tick += tickSpacing)
{
yield return ValueToAngle(tick);
}
}
}
我控:
<Controllers:Gauge
x:Name="gauge"
Minimum="0"
Maximum="100"
NeedleBrush="Transparent"
ScaleTickBrush="Transparent"
ScaleBrush="Red"
ScaleWidth="30"
TickBrush="Red"
TrailBrush="LightSeaGreen"
ValueBrush="Orange"
ValueStringFormat="N1"
Width="220"
Height="220"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Margin="0,0,0,0">
所以我想输出我的 TickWidth
属性 以便能够更改它(圆圈周围的红线),所以我将其添加到我的 Gauge.cs
文件中:
public static readonly DependencyProperty TickWidthProperty =
DependencyProperty.Register("TickWidth", typeof(double), typeof(Gauge), new PropertyMetadata(0.0));
public double TickWidth
{
get { return (double)GetValue(TickWidthProperty); }
set { SetValue(TickWidthProperty, value); }
}
在我的 Gauge.xaml
文件中,我替换了里面的 Width
属性 (Width="8"
):
<Rectangle Height="15"
Width="8"
Fill="{Binding Fill, ElementName=TicksProxy}">
<Rectangle.RenderTransform>
<TransformGroup>
<TranslateTransform X="-2.5"
Y="-95" />
<RotateTransform Angle="{Binding}" />
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
有:
Width="{TemplateBinding TickWidth}"
但是出现错误:
Error 40 The member "TickWidth" is not recognized or is not
accessible.
您可以使用 {RelativeSource}
绑定到父控件的 属性:
Width="{Binding TickWidth, RelativeSource={RelativeSource AncestorType=UserControl}}"
或者
Width="{Binding TickWidth, RelativeSource={RelativeSource AncestorType=controlsGauge:Gauge}}"
所以我有这个 Gauge
:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controlsGauge="clr-namespace:MyApplication.Controllers">
Gauge.xaml
<Style TargetType="controlsGauge:Gauge">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controlsGauge:Gauge">
<Viewbox>
<Grid Height="200"
Width="200">
<!-- Ticks -->
<Line x:Name="TicksProxy"
Visibility="Collapsed"
Fill="{TemplateBinding TickBrush}" />
<ItemsControl ItemsSource="{TemplateBinding Ticks}"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Height="15"
Width="8"
Fill="{Binding Fill, ElementName=TicksProxy}">
<Rectangle.RenderTransform>
<TransformGroup>
<TranslateTransform X="-2.5"
Y="-95" />
<RotateTransform Angle="{Binding}" />
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- Scale -->
<Path Name="PART_Scale"
Stroke="{TemplateBinding ScaleBrush}"
StrokeThickness="{TemplateBinding ScaleWidth}" />
<!-- Trail -->
<Path Name="PART_Trail"
Stroke="{TemplateBinding TrailBrush}"
StrokeThickness="{TemplateBinding ScaleWidth}" />
<!-- Scale Ticks -->
<Line x:Name="ScaleTicksProxy"
Visibility="Collapsed"
Fill="{TemplateBinding ScaleTickBrush}"
X1="{TemplateBinding ScaleWidth}" />
<ItemsControl ItemsSource="{TemplateBinding Ticks}"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Height="{Binding X1, ElementName=ScaleTicksProxy}"
Width="2"
Fill="{Binding Fill, ElementName=ScaleTicksProxy}">
<Rectangle.RenderTransform>
<TransformGroup>
<TranslateTransform X="-0.5"
Y="-77" />
<RotateTransform Angle="{Binding}" />
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- Value and Unit -->
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,145,0,0">
<StackPanel.RenderTransform>
<RotateTransform Angle="0.5"/>
</StackPanel.RenderTransform>
<StackPanel Orientation="Horizontal">
<TextBlock Name="PART_ValueText"
Foreground="Orange"
FontSize="16"
FontFamily="Comic Sans MS"
FontWeight="SemiBold"
Text="{TemplateBinding Value}"
TextAlignment="Center"
Margin="0 0 0 0" />
<TextBlock Foreground="Orange"
FontSize="16"
FontFamily="Comic Sans MS"
FontWeight="SemiBold"
Text="%"
Margin="0 0 0 0" />
</StackPanel>
<TextBlock Foreground="{TemplateBinding UnitBrush}"
FontSize="16"
TextAlignment="Center"
Text="{TemplateBinding Unit}"
Margin="0" />
</StackPanel>
<!-- Needle -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- The RenderTransform is in code behind. -->
<Path Name="PART_Needle"
Stretch="Uniform"
HorizontalAlignment="Center"
Fill="{TemplateBinding NeedleBrush}"
Data="M 0,0 l 0,100 l 5,0 l 0,-100 l -5,0"
RenderTransformOrigin="0.5,1">
</Path>
</Grid>
</Grid>
</Viewbox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Gauge.cs
[TemplatePart(Name = NeedlePartName, Type = typeof(Path))]
[TemplatePart(Name = ScalePartName, Type = typeof(Path))]
[TemplatePart(Name = TrailPartName, Type = typeof(Path))]
[TemplatePart(Name = ValueTextPartName, Type = typeof(TextBlock))]
public class 仪表:UserControl { #region常量
private const string NeedlePartName = "PART_Needle";
private const string ScalePartName = "PART_Scale";
private const string TrailPartName = "PART_Trail";
private const string ValueTextPartName = "PART_ValueText";
private const double Degrees2Radians = Math.PI / 180;
#endregion Constants
#region Dependency Property Registrations
public static readonly DependencyProperty MinimumProperty =
DependencyProperty.Register("Minimum", typeof(double), typeof(Gauge), new PropertyMetadata(0.0));
public static readonly DependencyProperty MaximumProperty =
DependencyProperty.Register("Maximum", typeof(double), typeof(Gauge), new PropertyMetadata(100.0));
public static readonly DependencyProperty ScaleWidthProperty =
DependencyProperty.Register("ScaleWidth", typeof(Double), typeof(Gauge), new PropertyMetadata(26.0));
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(double), typeof(Gauge), new PropertyMetadata(0.0, OnValueChanged));
public static readonly DependencyProperty UnitProperty =
DependencyProperty.Register("Unit", typeof(string), typeof(Gauge), new PropertyMetadata(string.Empty));
public static readonly DependencyProperty NeedleBrushProperty =
DependencyProperty.Register("NeedleBrush", typeof(Brush), typeof(Gauge), new PropertyMetadata(new SolidColorBrush(Colors.OrangeRed)));
public static readonly DependencyProperty ScaleBrushProperty =
DependencyProperty.Register("ScaleBrush", typeof(Brush), typeof(Gauge), new PropertyMetadata(new SolidColorBrush(Colors.LightGray)));
public static readonly DependencyProperty TickBrushProperty =
DependencyProperty.Register("TickBrush", typeof(Brush), typeof(Gauge), new PropertyMetadata(new SolidColorBrush(Colors.DimGray)));
public static readonly DependencyProperty TrailBrushProperty =
DependencyProperty.Register("TrailBrush", typeof(Brush), typeof(Gauge), new PropertyMetadata(new SolidColorBrush(Colors.Orange)));
public static readonly DependencyProperty ValueBrushProperty =
DependencyProperty.Register("ValueBrush", typeof(Brush), typeof(Gauge), new PropertyMetadata(new SolidColorBrush(Colors.DimGray)));
public static readonly DependencyProperty ScaleTickBrushProperty =
DependencyProperty.Register("ScaleTickBrush", typeof(Brush), typeof(Gauge), new PropertyMetadata(new SolidColorBrush(Colors.White)));
public static readonly DependencyProperty UnitBrushProperty =
DependencyProperty.Register("UnitBrush", typeof(Brush), typeof(Gauge), new PropertyMetadata(new SolidColorBrush(Colors.DimGray)));
public static readonly DependencyProperty ValueStringFormatProperty =
DependencyProperty.Register("ValueStringFormat", typeof(string), typeof(Gauge), new PropertyMetadata("N0"));
protected static readonly DependencyProperty ValueAngleProperty =
DependencyProperty.Register("ValueAngle", typeof(double), typeof(Gauge), new PropertyMetadata(null));
public static readonly DependencyProperty TicksProperty =
DependencyProperty.Register("Ticks", typeof(IEnumerable<double>), typeof(Gauge), new PropertyMetadata(null));
#endregion Dependency Property Registrations
#region Constructors
public Gauge()
{
this.DefaultStyleKey = typeof(Gauge);
this.Ticks = this.getTicks();
}
#endregion Constructors
#region Properties
public double Minimum
{
get { return (double)GetValue(MinimumProperty); }
set { SetValue(MinimumProperty, value); }
}
public double Maximum
{
get { return (double)GetValue(MaximumProperty); }
set { SetValue(MaximumProperty, value); }
}
public Double ScaleWidth
{
get { return (Double)GetValue(ScaleWidthProperty); }
set { SetValue(ScaleWidthProperty, value); }
}
public double Value
{
get { return (double)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public string Unit
{
get { return (string)GetValue(UnitProperty); }
set { SetValue(UnitProperty, value); }
}
public Brush NeedleBrush
{
get { return (Brush)GetValue(NeedleBrushProperty); }
set { SetValue(NeedleBrushProperty, value); }
}
public Brush TrailBrush
{
get { return (Brush)GetValue(TrailBrushProperty); }
set { SetValue(TrailBrushProperty, value); }
}
public Brush ScaleBrush
{
get { return (Brush)GetValue(ScaleBrushProperty); }
set { SetValue(ScaleBrushProperty, value); }
}
public Brush ScaleTickBrush
{
get { return (Brush)GetValue(ScaleTickBrushProperty); }
set { SetValue(ScaleTickBrushProperty, value); }
}
public Brush TickBrush
{
get { return (Brush)GetValue(TickBrushProperty); }
set { SetValue(TickBrushProperty, value); }
}
public Brush ValueBrush
{
get { return (Brush)GetValue(ValueBrushProperty); }
set { SetValue(ValueBrushProperty, value); }
}
public Brush UnitBrush
{
get { return (Brush)GetValue(UnitBrushProperty); }
set { SetValue(UnitBrushProperty, value); }
}
public string ValueStringFormat
{
get { return (string)GetValue(ValueStringFormatProperty); }
set { SetValue(ValueStringFormatProperty, value); }
}
public double ValueAngle
{
get { return (double)GetValue(ValueAngleProperty); }
set { SetValue(ValueAngleProperty, value); }
}
public IEnumerable<double> Ticks
{
get { return (IEnumerable<double>)GetValue(TicksProperty); }
set { SetValue(TicksProperty, value); }
}
#endregion Properties
public override void OnApplyTemplate()
{
// Draw Scale
var scale = this.GetTemplateChild(ScalePartName) as Path;
if (scale != null)
{
var pg = new PathGeometry();
var pf = new PathFigure();
pf.IsClosed = false;
var middleOfScale = 77 - this.ScaleWidth / 2;
pf.StartPoint = this.ScalePoint(-150, middleOfScale);
var seg = new ArcSegment();
seg.SweepDirection = SweepDirection.Clockwise;
seg.IsLargeArc = true;
seg.Size = new Size(middleOfScale, middleOfScale);
seg.Point = this.ScalePoint(150, middleOfScale);
pf.Segments.Add(seg);
pg.Figures.Add(pf);
scale.Data = pg;
}
OnValueChanged(this, new DependencyPropertyChangedEventArgs());
base.OnApplyTemplate();
}
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Gauge c = (Gauge)d;
if (!Double.IsNaN(c.Value))
{
var middleOfScale = 77 - c.ScaleWidth / 2;
var needle = c.GetTemplateChild(NeedlePartName) as Path;
var valueText = c.GetTemplateChild(ValueTextPartName) as TextBlock;
c.ValueAngle = c.ValueToAngle(c.Value);
// Needle
if (needle != null)
{
needle.RenderTransform = new RotateTransform() { Angle = c.ValueAngle };
}
// Trail
var trail = c.GetTemplateChild(TrailPartName) as Path;
if (trail != null)
{
if (c.ValueAngle > -146)
{
trail.Visibility = Visibility.Visible;
var pg = new PathGeometry();
var pf = new PathFigure();
pf.IsClosed = false;
pf.StartPoint = c.ScalePoint(-150, middleOfScale);
var seg = new ArcSegment();
seg.SweepDirection = SweepDirection.Clockwise;
// We start from -150, so +30 becomes a large arc.
seg.IsLargeArc = c.ValueAngle > 30;
seg.Size = new Size(middleOfScale, middleOfScale);
seg.Point = c.ScalePoint(c.ValueAngle, middleOfScale);
pf.Segments.Add(seg);
pg.Figures.Add(pf);
trail.Data = pg;
}
else
{
trail.Visibility = Visibility.Collapsed;
}
}
// Value Text
if (valueText != null)
{
valueText.Text = c.Value.ToString(c.ValueStringFormat);
}
}
}
private Point ScalePoint(double angle, double middleOfScale)
{
return new Point(100 + Math.Sin(Degrees2Radians * angle) * middleOfScale, 100 - Math.Cos(Degrees2Radians * angle) * middleOfScale);
}
private double ValueToAngle(double value)
{
double minAngle = -150;
double maxAngle = 150;
// Off-scale to the left
if (value < this.Minimum)
{
return minAngle - 7.5;
}
// Off-scale to the right
if (value > this.Maximum)
{
return maxAngle + 7.5;
}
double angularRange = maxAngle - minAngle;
return (value - this.Minimum) / (this.Maximum - this.Minimum) * angularRange + minAngle;
}
private IEnumerable<double> getTicks()
{
double tickSpacing = (this.Maximum - this.Minimum) / 10;
for (double tick = this.Minimum; tick <= this.Maximum; tick += tickSpacing)
{
yield return ValueToAngle(tick);
}
}
}
我控:
<Controllers:Gauge
x:Name="gauge"
Minimum="0"
Maximum="100"
NeedleBrush="Transparent"
ScaleTickBrush="Transparent"
ScaleBrush="Red"
ScaleWidth="30"
TickBrush="Red"
TrailBrush="LightSeaGreen"
ValueBrush="Orange"
ValueStringFormat="N1"
Width="220"
Height="220"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Margin="0,0,0,0">
所以我想输出我的 TickWidth
属性 以便能够更改它(圆圈周围的红线),所以我将其添加到我的 Gauge.cs
文件中:
public static readonly DependencyProperty TickWidthProperty =
DependencyProperty.Register("TickWidth", typeof(double), typeof(Gauge), new PropertyMetadata(0.0));
public double TickWidth
{
get { return (double)GetValue(TickWidthProperty); }
set { SetValue(TickWidthProperty, value); }
}
在我的 Gauge.xaml
文件中,我替换了里面的 Width
属性 (Width="8"
):
<Rectangle Height="15"
Width="8"
Fill="{Binding Fill, ElementName=TicksProxy}">
<Rectangle.RenderTransform>
<TransformGroup>
<TranslateTransform X="-2.5"
Y="-95" />
<RotateTransform Angle="{Binding}" />
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
有:
Width="{TemplateBinding TickWidth}"
但是出现错误:
Error 40 The member "TickWidth" is not recognized or is not accessible.
您可以使用 {RelativeSource}
绑定到父控件的 属性:
Width="{Binding TickWidth, RelativeSource={RelativeSource AncestorType=UserControl}}"
或者
Width="{Binding TickWidth, RelativeSource={RelativeSource AncestorType=controlsGauge:Gauge}}"