Windows Phone 7的自定义仪表控件:第一部分






4.91/5 (61投票s)
本系列的第一篇文章介绍了在 WP7 中实现和使用一些自定义仪表盘控件的注意事项。
引言
本文是本系列的第一篇,旨在介绍我为 Windows Phone 7 实现的一些自定义仪表盘控件。第一篇文章将介绍各种设计注意事项、自定义控件的使用方法以及一些高级配置示例。本系列后续文章将深入探讨问题,并尝试解释这些控件(刻度盘和指示器)的实现。
本系列文章
您可以在下方找到本系列所有文章的列表
文章内容
抢先预览
以下图像展示了使用自定义仪表盘控件可以实现的效果的抢先预览
设计考量
在我看来,仪表盘应包含一个刻度盘,并允许多个指示器指向该刻度盘内的特定值。当我提到“刻度盘”时,我的意思是仪表盘应包含除指示器之外的所有内容。这意味着,在我看来,刻度盘应包含刻度线(小刻度和大刻度)、标签和范围。我使用范围来为刻度盘中的不同区间分配不同的颜色。这些范围可用于指示低于最佳、最佳或高于最佳值。
总的来说,刻度盘应向用户提供以下属性
- 最小值 – 刻度盘中的最小值。指示器不能指向此值以下。
- 最大值 – 刻度盘中的最大值。指示器不能指向此值以上。
- 小刻度步长 – 小刻度线将放置在步长的倍数值处,从最小值开始但不包括最小值。例如,小刻度线将放置在最小值 + 步长、最小值 + 2*步长等处。
- 大刻度步长 – 大刻度线将放置在步长的倍数值处,从最小值开始(包括最小值)。例如,大刻度线将放置在最小值、最小值 + 步长等处。当当前值同时是小刻度和大刻度的候选值时,大刻度线将优先。
- 范围 – 这些将指示刻度盘上的最佳范围。例如,在一个从 0 到 100 的刻度盘中,用户可以指定低于 50 的值为最佳值。
- RangeThickness – 指定范围的厚度。
- UseDefaultRange – 指定是否使用默认范围。这将起到在刻度线下方绘制一条线的效果。
- DefaultRangeColor - 如果启用了默认范围,则用于默认范围的颜色。
- DefaultTickColor - 用于绘制默认刻度线和标签的颜色
- UseRangeColorsForTicks – 指定是否使用范围颜色来绘制属于特定范围的刻度线。这意味着如果我们有 3 个具有 3 种不同颜色的范围,并且此属性设置为 true,那么在每个范围内的刻度线将以该范围的颜色绘制。此属性仅在刻度线和标签具有默认模板时适用。
- 指示器 – 此集合将包含特定刻度盘的所有指示器。
- 小刻度模板、大刻度模板和标签模板 – 这些属性指定显示刻度线和标签时将使用的模板。
有两种刻度盘:线性刻度盘和径向刻度盘。它们各自将添加上述属性。本文将介绍这两种刻度盘的实现。
线性刻度盘
对于线性刻度盘,我们将有以下附加属性
- 方向 – 指定刻度盘是水平还是垂直。
- 刻度线放置 – 指定刻度线在刻度盘上的位置。在此,对于水平刻度盘,刻度线可以位于指示器上方或下方;对于垂直刻度盘,刻度线可以位于指示器左侧或右侧。
径向刻度盘
对于径向刻度盘,我们将有以下附加属性
- 最小角度 – 指定旋转开始的最小角度。
- 最大角度 – 指定旋转停止的最大角度。
- 扫掠方向 – 指定旋转方向。
- EnableLabelRotation - 指定标签是否旋转以跟随控件的轮廓。
- 刻度线放置 – 指定刻度线的位置。径向刻度盘的刻度线可以放置在内侧或外侧。
- 径向类型 – 对于径向刻度盘,还有一个额外的问题。我们可以有一个完整的圆形刻度盘、一个半圆形刻度盘或一个象限刻度盘。此选项主要用于节省屏幕空间。例如,如果用户选择 90 度范围,他可能不想浪费圆的其余三个象限。为了节省空间,他可以指定他想要一个象限。此属性将与最小角度、最大角度和扫掠方向属性结合使用。此属性将影响刻度盘区域内旋转中心的定位以及范围。如果角度和扫掠方向不匹配,用户可以选择更改它们以获得所需效果。这比在代码中实现复杂的逻辑来确定象限并强制转换角度值要容易。
从上述属性可以看出,我选择在派生类中实现刻度线放置。这是为了进一步阐明属性的含义。基类中带有枚举中更多选项的单个属性会使用户感到困惑。
上图展示了刻度盘控件的类层次结构
在上图中,您可以看到基类是抽象的,并且它是一个 `Panel`。用户只能实例化派生实例。
指示器
对于两种类型的刻度盘,都可以有相当多的指示器。我们可以有条形指示器(适用于径向和线性刻度盘)、箭头指示器(适用于线性刻度盘)、标记指示器(适用于径向和线性刻度盘)或针式指示器(适用于径向刻度盘)。指示器有两个自定义属性:`Value` 属性和 `Owner` 属性。后者标识拥有指示器的刻度盘。
条形指示器有两个附加属性:`BarThickness` 和 `BarBrush`。标记指示器有一个附加属性:`MarkerTemplate`。
您可以在下图中看到指示器的类层次结构
使用代码
刻度盘和指示器非常易于使用。第一步是添加对包含刻度盘的程序集的引用,并在要添加控件的页面文件中引用该程序集。这是程序集引用字符串
xmlns:scada="clr-namespace:WPScadaControlsV2;assembly=WPScadaControlsV2"
之后,您可以在页面中实例化一个刻度盘。下面的 XAML 展示了一个两行网格。每行包含一个刻度盘。顶行包含一个径向刻度盘,底行包含一个线性刻度盘。
<Grid x:Name="ContentGrid" Grid.Row="1" Margin="5" >
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<scada:RadialScale></scada:RadialScale>
<scada:LinearScale Grid.Row="1"/>
</Grid>
此代码的效果可以在下图中看到
从上图可以看出,只需少量代码,您就可以获得一些非常好的仪表盘。这是两种刻度盘的默认行为。在接下来的部分,我将讨论自定义选项。
基本刻度和标签自定义
有八个属性可用于自定义刻度线和标签。它们是:`MinorTickStep`、`MajorTickStep`、`MinorTickTemplate`、`MajorTickTemplate`、`LabelTemplate`、`EnableLabelRotation`、`DefaultTickColor` 和 `TickPlacement`。最后一个属性(`TickPlacement`)在派生的刻度盘类中实现。我们可以进行线性或径向刻度线放置。
第一个刻度线自定义示例展示了如何修改刻度盘上显示的刻度线和标签的数量。此数量可以通过使用 `MinorTickStep` 和 `MajorTickStep` 属性进行修改。
<scada:RadialScale MinorTickStep="10" MajorTickStep="20"></scada:RadialScale>
<scada:LinearScale Grid.Row="1" MinorTickStep="5" MajorTickStep="25"/>
此代码的效果可以在下方看到
下一个示例将展示如何修改刻度线和标签模板。XAML 可以在下方看到
<scada:RadialScale Margin="5" UseDefaultRange="False" DefaultTickColor="Gold">
<scada:RadialScale.MinorTickTemplate>
<DataTemplate>
<Ellipse Width="3" Height="3" Fill="White"/>
</DataTemplate>
</scada:RadialScale.MinorTickTemplate>
<scada:RadialScale.MajorTickTemplate>
<DataTemplate>
<Ellipse Width="6" Height="6" Fill="Red"/>
</DataTemplate>
</scada:RadialScale.MajorTickTemplate>
</scada:RadialScale>
<scada:LinearScale Grid.Row="1" Margin="10" MajorTickStep="20"
DefaultTickColor="Goldenrod">
<scada:LinearScale.MinorTickTemplate>
<DataTemplate>
<Rectangle Width="2" Height="6" Fill="White"/>
</DataTemplate>
</scada:LinearScale.MinorTickTemplate>
<scada:LinearScale.MajorTickTemplate>
<DataTemplate>
<Path Data="M0,0 L8,0 L4,12 Z" Fill="Red"/>
</DataTemplate>
</scada:LinearScale.MajorTickTemplate>
</scada:LinearScale>
上面的 XAML 还使用了 `DefaultTickColor` 属性。顾名思义,此属性用于指定刻度线的默认颜色。此代码的效果可以在下图看到
通过修改刻度线模板可以获得许多非常好的效果。下面的 XAML 展示了一个额外的示例
<scada:RadialScale.MinorTickTemplate>
<DataTemplate>
<Rectangle Fill="Green" Width="5" Height="10"/>
</DataTemplate>
</scada:RadialScale.MinorTickTemplate>
<scada:RadialScale.MajorTickTemplate>
<DataTemplate>
<Path Data="M0,0 L10,0 L5,20 Z" Fill="Purple"/>
</DataTemplate>
</scada:RadialScale.MajorTickTemplate>
<scada:RadialScale.LabelTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" FontWeight="Bold"
Foreground="Red"/>
</DataTemplate>
</scada:RadialScale.LabelTemplate>
下图展示了将这些模板应用于线性和径向刻度盘的结果
接下来要讨论的刻度线相关属性是 `TickPlacement` 属性。对于上图中的控件,刻度线放置设置为默认值。这些值是径向刻度盘的 `Outward`(向外)和线性刻度盘的 `TopLeft`(左上)。
下图展示了相同的控件,但这次 `TickPlacement` 属性设置为 `Inward`(向内)(径向刻度盘)和 `BottomRight`(右下)(线性刻度盘)。
关于刻度线自定义要讨论的最后一个属性是 `EnableLabelRotation` 属性。此布尔属性决定是否旋转标签以跟随刻度盘的轮廓。默认情况下,此属性设置为 true,这意味着标签将被旋转。将此属性设置为 false,将不进行标签旋转。为了看到此属性的效果,下图展示了两个刻度盘:一个具有默认值,一个将属性设置为 false。
使用范围
刻度盘定义了五个与范围相关的属性。它们是:`UseDefaultRange`、`DefaultRangeColor`、`Ranges`、`RangeThickness` 和 `UseRangeColorsForTicks`。
到目前为止,您看到的绝大多数刻度盘(线性和径向)在刻度线下方或上方都画有一条线。这条线代表默认的刻度盘范围。线性和径向刻度盘还为用户提供了添加附加范围的可能性。范围可以代表最佳范围。可以通过使用 `UseDefaultRange` 布尔属性来选择默认范围的使用。如果我们将上图中两个控件的此属性设置为 `false`,我们将得到下图所示的结果
关于默认范围,用户还可以使用 `DefaultRangeColor` 属性。顾名思义,此属性决定了默认范围的颜色(如果该范围正在使用)。下图展示了一个设置了此属性的刻度盘。此图可以与上面具有默认值的图进行比较。
上面的刻度盘是使用下面的代码构建的。
<scada:RadialScale Grid.RowSpan="2" Grid.ColumnSpan="2"
RangeThickness="5" MinorTickStep="5" MajorTickStep="10"
MinAngle="-90" MaxAngle="180" EnableLabelRotation="False"
DefaultRangeBrush="{StaticResource PhoneAccentBrush}" >
</scada:RadialScale>
这两个默认范围属性(`UseDefaultRange` 和 `DefaultRangeColor`)可以通过使用自定义范围来复制,正如您将在接下来的段落中看到的。
除了此默认范围之外,用户还可以通过使用 `Ranges` 属性添加附加范围。下面的 XAML 展示了一个包含三个范围的集合。对于每个范围,用户可以设置颜色和最大值。此外,用户可以设置刻度盘的 `RangeThickness` 属性来控制范围的厚度。
<scada:RadialScale.Ranges>
<scada:GaugeRange Color="Green" Offset="30"/>
<scada:GaugeRange Color="Orange" Offset="60"/>
<scada:GaugeRange Color="Red" Offset="100"/>
</scada:RadialScale.Ranges>
结果可以在下图看到。在这种情况下,范围厚度已设置为 5。
下图展示了相同的设置,但这次 `TickPlacement` 属性设置为 `Inward`。
最后一个剩余的范围相关属性是 `UseRangeColorsForTicks` 属性。顾名思义,此属性将使刻度线和标签能够使用其相应范围的颜色进行绘制。
下面的 XAML 展示了一个使用此属性的两个径向刻度盘的示例
<scada:RadialScale Margin="5" RangeThickness="5" UseRangeColorsForTicks="True">
<scada:RadialScale.Ranges>
<scada:GaugeRange Offset="30" Color="{StaticResource PhoneAccentColor}"/>
<scada:GaugeRange Offset="60" Color="Gold"/>
<scada:GaugeRange Offset="90" Color="Red"/>
</scada:RadialScale.Ranges>
</scada:RadialScale>
<scada:RadialScale Grid.Column="1" Margin="5"
RangeThickness="5" UseRangeColorsForTicks="True"
DefaultRangeColor="Red">
</scada:RadialScale>
使用此代码的结果可以在下图看到
从上图可以看出,如果属性设置为 `true` 且未定义范围,则刻度线和标签将使用 `DefaultRangeColor` 属性值进行绘制。如果定义了范围,则刻度线和标签将使用相应的颜色。`UseRangeColorsForTicks` 属性旨在用最少的代码和精力(无需使用模板)来添加更多刻度线自定义。因此,该属性仅在刻度线使用默认模板时适用。
使用模板可以获得相同的效果,但我将在高级自定义部分讨论这一点。
最小角度、最大角度和扫掠方向
另一组有助于您自定义径向控件的属性是最小和最大角度以及扫掠方向。这些属性的作用与它们的名称一样:它们定义了用于绘制刻度线和范围的弧。下图展示了一些示例
径向类型
可用于自定义径向仪表盘的最后一个属性是 `RadialType` 属性。如我在文章前面所述,此属性可用于最小化径向仪表盘在角度跨度在特定区间内的空间占用。例如,如果角度跨度小于 90 度,您可以使用 `RadialType` 的 `Quarter` 来仅占用整个圆的四分之一。半圆形也是如此。此属性将检查最小角度、最大角度和扫掠方向属性以计算控件的最佳布局。下图展示了一些说明此属性用法的示例
高级刻度盘自定义
到目前为止,您已经看到了许多展示了可以在两种刻度盘上设置的所有属性的示例。本节将讨论一些更高级的自定义选项。这些选项指的是更高级地使用刻度线和标签模板。
本节将展示如何结合使用值转换器和模板属性,以获得一些激进的效果。这些效果包括
- 根据值更改刻度线的颜色。
- 根据值更改刻度线和标签的形状。
- 根据值在刻度线和标签中添加渐变。
为了自定义刻度盘,我创建了四个自定义值转换器。第一个值转换器用于根据特定范围将刻度线值转换为颜色。该转换器称为 `RangeColorConverter`,可以在下面的代码中看到
public class ColorRange
{
public double Minimum { get; set; }
public double Maximum { get; set; }
public Color Color { get; set; }
}
[ContentProperty("Ranges")]
public class RangeColorConverter:IValueConverter
{
public ObservableCollection<ColorRange> Ranges { get; set; }
public Color DefaultColor { get; set; }
public RangeColorConverter()
{
Ranges = new ObservableCollection<ColorRange>();
DefaultColor = Colors.White;
}
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
double val = (double)value;
for (int i = 0; i < Ranges.Count; i++)
{
if (Ranges[i].Minimum <val && val <= Ranges[i].Maximum)
return new SolidColorBrush(Ranges[i].Color);
}
return new SolidColorBrush(DefaultColor);
}
public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
如您所见,`Convert` 方法会找到值所属的范围,并返回一个基于该值的 `SolidColorBrush`。下面的代码展示了一个使用此转换器的刻度盘
<loc:RangeColorConverter x:Key="colConv">
<loc:ColorRange Color="Red" Minimum="20" Maximum="40"/>
<loc:ColorRange Color="Blue" Minimum="60" Maximum="80"/>
</loc:RangeColorConverter>
//...
<scada:RadialScale Grid.Column="1" MajorTickStep="5">
<scada:RadialScale.MajorTickTemplate>
<DataTemplate>
<Rectangle Width="2" Height="10"
Fill="{Binding Converter={StaticResource colConv}}"/>
</DataTemplate>
</scada:RadialScale.MajorTickTemplate>
</scada:RadialScale>
运行此代码的结果可以在下方看到
第二个转换器(`GradientConverter`)与第一个类似,但它用于计算渐变。实现可以在下面看到
public class GradientConverter:IValueConverter
{
public Color StartColor { get; set; }
public Color EndColor { get; set; }
public Color DefaultColor { get; set; }
public double StartValue { get; set; }
public double EndValue { get; set; }
public GradientConverter()
{
DefaultColor = Colors.White;
StartColor = Colors.White;
EndColor = Colors.White;
}
public object Convert(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
double val=(double)value;
int n = (int)(EndValue - StartValue);
int curr = (int)(val-StartValue);
Color newColor = DefaultColor;
if(val>=StartValue && val<=EndValue)
{
double u=(double)curr/n;
newColor.R = (byte)(StartColor.R * (1 - u) + EndColor.R * u);
newColor.G = (byte)(StartColor.G * (1 - u) + EndColor.G * u);
newColor.B = (byte)(StartColor.B * (1 - u) + EndColor.B * u);
}
return new SolidColorBrush(newColor);
}
public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
下面的代码展示了此类转换器的用法
<loc:GradientConverter x:Key="conv1" EndColor="Blue"
StartColor="Red" StartValue="64" EndValue="90" />
<scada:RadialScale Grid.Row="1" MajorTickStep="5">
<scada:RadialScale.MajorTickTemplate>
<DataTemplate>
<Rectangle Width="2" Height="10"
Fill="{Binding Converter={StaticResource conv1}}"/>
</DataTemplate>
</scada:RadialScale.MajorTickTemplate>
</scada:RadialScale>
下图展示了结果
第三个转换器(`SizeConverter`)用于根据刻度线值和范围返回一个大小。定义可以在下面看到
public class SizeConverter:IValueConverter
{
public double StartSize { get; set; }
public double EndSize { get; set; }
public double DefaultSize { get; set; }
public double StartValue { get; set; }
public double EndValue { get; set; }
public SizeConverter()
{
StartSize = EndSize = DefaultSize = 10;
}
public object Convert(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
double val = (double)value;
double size = DefaultSize;
if (val >= StartValue && val <= EndValue && EndValue != StartValue)
{
size = StartSize + (EndSize - StartSize) * val / (EndValue - StartValue);
}
return size;
}
public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
下面的代码展示了如何使用此转换器
<loc:SizeConverter x:Key="conv2" EndValue="50" StartSize="3" EndSize="15" />
<scada:RadialScale Grid.Row="1" Grid.Column="1" MajorTickStep="5">
<scada:RadialScale.MajorTickTemplate>
<DataTemplate>
<Rectangle Width="2"
Height="{Binding Converter={StaticResource conv2}}"
Fill="White"/>
</DataTemplate>
</scada:RadialScale.MajorTickTemplate>
</scada:RadialScale>
下图展示了结果
最后一个转换器(`RangeTemplateConverter`)是最通用的。它用于根据值更改刻度线和标签模板。它类似于 WPF 中的模板选择器。该转换器的定义可以在下面看到
public class TemplateRange
{
public double Minimum { get; set; }
public double Maximum { get; set; }
public DataTemplate Template { get; set; }
}
[ContentProperty("Ranges")]
public class RangeTemplateConverter:IValueConverter
{
public ObservableCollection<TemplateRange> Ranges { get; set; }
public DataTemplate DefaultTemplate { get; set; }
public RangeTemplateConverter()
{
Ranges = new ObservableCollection<TemplateRange>();
}
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
double val = (double)value;
for (int i = 0; i < Ranges.Count; i++)
{
if (Ranges[i].Minimum < val && val <= Ranges[i].Maximum)
return Ranges[i].Template;
}
return DefaultTemplate;
}
public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
下面的列表中的 XAML 展示了如何使用此转换器。
<loc:GradientConverter x:Key="conv1" EndColor="Blue"
StartColor="Red" StartValue="64" EndValue="90" />
<loc:SizeConverter x:Key="conv2" EndValue="50" StartSize="3" EndSize="15" />
<DataTemplate x:Key="defTemplate">
<Rectangle Width="2" Height="{Binding Converter={StaticResource conv2}}" Fill="White"/>
</DataTemplate>
<loc:RangeTemplateConverter x:Key="conv3" DefaultTemplate="{StaticResource defTemplate}" >
<loc:TemplateRange Minimum="60" Maximum="90" >
<loc:TemplateRange.Template>
<DataTemplate>
<Path Data="M0,0 L10,0 L5,10 Z"
Fill="{Binding Converter={StaticResource conv1}}"/>
</DataTemplate>
</loc:TemplateRange.Template>
</loc:TemplateRange>
</loc:RangeTemplateConverter>
//...
<scada:RadialScale MinorTickStep="5" MajorTickStep="5">
<scada:RadialScale.MajorTickTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding}"
ContentTemplate="{Binding Converter={StaticResource conv3}}"/>
</DataTemplate>
</scada:RadialScale.MajorTickTemplate>
</scada:RadialScale>
结果可以在下图中看到
这个例子展示了一种结合使用各种值转换器来实现所需结果的方法。当然,还有很多其他方法可以自定义这些刻度盘。这些示例仅展示了一小部分可能的操作。
添加指示器
正如您在文章开头看到的,我已经实现了四个具体的指示器类。我将首先介绍条形指示器。这些指示器可以添加到径向和线性刻度盘中。下面的 XAML 展示了两种刻度盘类型的条形指示器
<scada:RadialBarIndicator Value="{Binding ElementName=slider, Path=Value}"
BarThickness="20" BarBrush="{StaticResource PhoneAccentBrush}" />
<scada:LinearBarIndicator Value="{Binding ElementName=slider, Path=Value}"
BarThickness="10" BarBrush="{StaticResource PhoneAccentBrush}"/>
上一个 XAML 中所示指示器的效果可以在下图看到
接下来我要介绍的指示器是针式指示器。它的使用方法与其他指示器相同。下图展示了一个针式指示器
该指示器是通过使用以下 XAML 创建的
<scada:NeedleIndicator Value="20" Background="GreenYellow"/>
实现的最后一个指示器是标记指示器。使用标记指示器,您可以通过数据模板在刻度盘的特定值处显示任何类型的形状。`MarkerIndicator` 可与线性刻度盘和径向刻度盘一起使用。下面的 XAML 展示了两个此类指示器的定义。第一个具有默认模板(白色矩形),第二个具有自定义模板(红色圆圈)。
<scada:MarkerIndicator Value="40" />
<scada:MarkerIndicator Value="20" >
<scada:MarkerIndicator.MarkerTemplate>
<DataTemplate>
<Ellipse Width="15" Height="15" Fill="Red"/>
</DataTemplate>
</scada:MarkerIndicator.MarkerTemplate>
</scada:MarkerIndicator>
使用此代码的结果可以在下图中看到
正如您在上图中所见,您可以在一个刻度盘中使用多个指示器。您还可以重叠刻度盘以获得一些非常酷的效果。下图展示了另一个示例
高级指示器自定义
到目前为止介绍的指示器影响很大,但您可以通过结合使用自定义值转换器和指示器 `Template` 属性来进一步自定义它们。以下示例将向您展示如何将应用于刻度盘的自定义值转换器也应用于进一步自定义指示器。
上图展示了处于不同阶段的单个指示器。指示器已自定义为根据其值更改颜色。在这种情况下,这是通过使用渐变转换器实现的。下面的代码展示了控件
<loc:GradientConverter x:Key="conv1" EndColor="Blue"
StartColor="Red" StartValue="64" EndValue="90" />
<scada:RadialScale MajorTickStep="25" >
<scada:NeedleIndicator Value="90"
Background="{Binding RelativeSource={RelativeSource Mode=Self},
Path=Value,Converter={StaticResource conv1}}"/>
</scada:RadialScale>
最后的想法
这就是我在这篇文章中想说的全部内容。请阅读本系列的其他文章,因为它们将深入探讨问题并介绍刻度盘和指示器的实现。您可以在顶部找到链接。
如果您喜欢这篇文章并且代码很有用,请花一分钟时间发表评论和投票。
历史
- 创建于 2011 年 3 月 7 日。
- 于 2011 年 3 月 23 日更新了源代码。
- 于 2011 年 3 月 28 日更新了文章和源代码。
- 于 2011 年 4 月 5 日更新了文章和源代码。
- 于 2011 年 4 月 10 日更新了文章和源代码。
- 于 2013 年 2 月 24 日更新了文章和源代码。