创建自定义圆形仪表盘控件

在开发应用程序时,经常需要展示一些数据的可视化形式,比如速度、温度、压力等。Silverlight3 SDK 和工具包提供了超过一百个控件,但缺少一个圆形仪表盘控件。因此,决定创建一个,目标是制作一个易于使用且外观专业的仪表盘。可以在这里看到实时演示。

使用代码

在本节中,将解释如何在应用程序中使用仪表盘控件。最简单的开始方式是复制下面的模板代码片段到项目中,前提是已经引用了CircularGauge.dll和CircularGauge命名空间。

<gauge:CircularGaugeControl x:Name="myGauge1" Grid.Column="0" Grid.Row="0" Radius="150" ScaleRadius="110" ScaleStartAngle="120" ScaleSweepAngle="300" PointerLength="85" PointerCapRadius="35" MinValue="0" MaxValue="1000" MajorDivisionsCount="10" MinorDivisionsCount="5" CurrentValue="{Binding Score}" ImageSource="silverlightlogo.png" ImageSize="60,50" RangeIndicatorThickness="8" RangeIndicatorRadius="120" RangeIndicatorLightRadius="10" RangeIndicatorLightOffset="80" ScaleLabelRadius="90" ScaleLabelSize="40,20" ScaleLabelFontSize="10" ScaleLabelForeground="LightGray" MajorTickSize="10,3" MinorTickSize="3,1" MajorTickColor="LightGray" MinorTickColor="LightGray" ImageOffset="-50" GaugeBackgroundColor="Black" PointerThickness="16" OptimalRangeStartValue="300" OptimalRangeEndValue="700" DialTextOffset="40" DialText="Black" DialTextColor="Black"> </gauge:CircularGaugeControl>

CircularGauge 控件提供了多种选项来完全自定义其所有元素。大多数属性设置都很直观,所以只会在这里讨论一些。

属性的设置可以改变控件的外观。例如:

  • Background: 设置背景颜色会自动创建渐变和玻璃效果,使用设置的颜色作为基础。这使得外观的改变变得非常容易。
  • ScaleRadius, ScaleLabelRadius, RangeIndicatorRadius: 这些属性提供了在仪表盘内放置刻度、范围指示器和刻度标签的选项。
  • CurrentValue: CurrentValue 属性是一个依赖属性,因此可以将其数据绑定。
  • ImageOffset, DialTextOffset, RangeIndicatorLightOffset: 这些属性控制图像、刻度文本和范围指示器光沿着 Y 轴相对于仪表盘中心的位置。
  • OptimalRangeStartValue, OptimalRangeEndValue: 这些属性帮助定义推荐的值范围。范围指示器根据这些值绘制。除了范围指示器,RangeIndicatorLight 也使用相同的信息提供视觉反馈。这些值区域的颜色可以使用 BelowOptimalRangeColor、AboveOptimalRangeColor 和 OptimalRangeColor 值自定义。

创建自定义模板

这是一个无样式控件,所以所有外观细节都在 generic.xaml 中指定的默认样式中描述。如果想创建一个新的控件模板,仪表盘控件在其控件模板中期望包含以下元素:

  • Element Name: Element Type
  • LayoutRoot: Grid
  • Pointer: Path
  • RangeIndicatorLight: Ellipse
  • PointerCap: Ellipse

可以在源代码中包含的 generic.xaml 文件中找到默认样式的完整标记。

创建过程要点

本节概述了创建此控件的主要步骤。仪表盘控件的大部分视觉表示都是使用 Expression Blend 绘制的。包含仪表盘所有元素的容器是一个 Grid。仪表盘/边缘、指针帽、指针、范围指示器光和玻璃效果(另一个带有降低透明度的椭圆)都是使用 Expression Blend 3 绘制的。绘制了形状,然后模板绑定了高度、宽度和其他属性。以下是指针的标记:

<Path x:Name="Pointer" Stroke="#FFE91C1C" StrokeThickness="2" Width="{TemplateBinding PointerLength}" Height="{TemplateBinding PointerThickness}" HorizontalAlignment="Center" Data="M1,1 L1,10 L156,6 z" Stretch="Fill" RenderTransformOrigin="0,0.5" RenderTransform="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=PointerLength, Converter={StaticResource pointerCenterConverter}}"> <Path.Fill> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="#FF890A0A" Offset="0.197"/> <GradientStop Color="#FFC40808" Offset="1"/> <GradientStop Color="#FFE32323" Offset="0.61"/> </LinearGradientBrush> </Path.Fill> </Path>

所有想要在代码中访问的模板项都需要适当命名。这是在用户界面和控件之间建立绑定的方式。然后重写 OnApplyTemplate 方法以获取 UI 中的命名元素。

绘制刻度和范围指示器

不能在 generic.xaml 文件中定义的元素是刻度和范围指示器,它们需要在代码中绘制。主要和次要刻度标记只是已经旋转和移动的矩形,使用渲染转换。类似于刻度标记,刻度标签是已经旋转和移动的文本块。为了绘制刻度,需要计算刻度圆周上的点的位置。这可以使用以下公式计算:

给定角度和半径找到圆周上的点的公式:

x = a + r * cos(θ) y = b + r * sin(θ)

其中:

  • r 是圆的半径
  • (a,b) 是圆的中心
  • (x,y) 是圆周上的点
  • θ 是角度(以度为单位)
  • radian = degree * π/180

类似于绘制刻度,使用相同的公式计算组成范围段的四个点。

指针动画

最后,动画指针只涉及创建一个双精度动画,并将目标设置为指针的旋转变换角度。

void AnimatePointer(double oldcurrentvalueAngle, double newcurrentvalueAngle) { if (pointer != null) { DoubleAnimation da = new DoubleAnimation(); da.From = oldcurrentvalueAngle; da.To = newcurrentvalueAngle; double animDuration = Math.Abs(oldcurrentvalueAngle - newcurrentvalueAngle) * animatingSpeedFactor; da.Duration = new Duration(TimeSpan.FromMilliseconds(animDuration)); Storyboard sb = new Storyboard(); sb.Completed += new EventHandler(sb_Completed); sb.Children.Add(da); Storyboard.SetTarget(da, pointer); Storyboard.SetTargetProperty(da, new PropertyPath("(Path.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)")); if (newcurrentvalueAngle != oldcurrentvalueAngle) { sb.Begin(); } } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485