所以我有Gauge
控件:
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="4"
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>
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 Gauge : UserControl
{
#region Constants
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);
}
}
}
主要XAML
:
xmlns:Controllers="clr-namespace:MyApplication.Controllers"
我的controls
:
<Controllers:Gauge
x:Name="gauge"
Minimum="0"
Maximum="100"
NeedleBrush="Transparent"
ScaleTickBrush="White"
ScaleBrush="White"
ScaleWidth="20"
TickBrush="White"
TrailBrush="SeaGreen"
ValueBrush="Orange"
ValueStringFormat="N1">
所以我想创建几个styles
,所以在我的Window.Resources
:
<Style x:Key="GaugesStyle1" TargetType="{x:Type Controllers:Gauge}">
<Setter Property="NeedleBrush" Value="Transparent"/>
<Setter Property="ScaleTickBrush" Value="White"/>
<Setter Property="ScaleBrush" Value="White"/>
<Setter Property="ScaleWidth" Value="20"/>
<Setter Property="TickBrush" Value="White"/>
<Setter Property="TrailBrush" Value="SeaGreen"/>
<Setter Property="ValueBrush" Value="Orange"/>
<Setter Property="ValueStringFormat" Value="N1"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
并更改了我的control
:
<Controllers:Gauge
x:Name="gauge"
Minimum="0"
Maximum="100"
Style="{StaticResource GaugesStyle1}">
现在我看不到我的Gauge
,它就消失了。
有什么建议吗?
答案 0 :(得分:1)
您的UserControl
没有任何默认样式,因此您需要在窗口中定义的Style
基于定义模板的第一个Style
。
这意味着您应该在某个全局资源字典中定义第一个Style
(例如App.xaml)并为其指定x:Key
。然后,您可以将第二种样式基于第一种样式:
<Style x:Key="GaugesStyle1" TargetType="{x:Type Controllers:Gauge}" BasedOn="{StaticResource theKeyOfTheFirstStyle}">
...
另一种选择是在GaugesStyle1
中重新定义整个模板,或者创建一个实际具有默认样式的自定义控件。
从Gauge
导出您的Control
课程,并将默认Style
放在名为ResourceDictionary
的名为Generic.xaml
的{{1}} {你项目的根源。