XAMLで作る簡単メーターコントロール
いつも、センサー、センサー、云うてますやん。データ計測したら見たいですやん。…という事で、XAMLで作るメーターコントロールを紹介します。
見た目は、こんな感じ。タイトルは変更可能、数字をセットすると針が動くというものです。
XAMLはざっと
<Canvas> <TextBlock Name="tbTitle" Text="Electric Power" FontSize="20" HorizontalAlignment="Center" Height="32" Width="200" Canvas.Left="20" Canvas.Top="0" /> <TextBlock Name="tbValue" Text="1000000" FontSize="20" Canvas.Top="38" Canvas.Left="75"/> <TextBlock Name="tbUnit" Text="Watt" FontSize="20" Canvas.Top="128" Canvas.Left="96"/><!-- 5つのRectangleは、目盛 --> <Rectangle Width="20" Height="4" > <Rectangle.Fill> <SolidColorBrush Color="Red"/> </Rectangle.Fill> <Rectangle.RenderTransform> <TranslateTransform X="10" Y="178"/> </Rectangle.RenderTransform> </Rectangle> <Rectangle Width="20" Height="4" > <Rectangle.Fill> <SolidColorBrush Color="Red"/> </Rectangle.Fill> <Rectangle.RenderTransform> <TransformGroup> <TranslateTransform X="10" Y="178"/> <RotateTransform CenterX="120" CenterY="180" Angle="45"/> </TransformGroup> </Rectangle.RenderTransform> </Rectangle> <Rectangle Width="20" Height="4" > <Rectangle.Fill> <SolidColorBrush Color="Red"/> </Rectangle.Fill> <Rectangle.RenderTransform> <TransformGroup> <TranslateTransform X="10" Y="178"/> <RotateTransform CenterX="120" CenterY="180" Angle="90"/> </TransformGroup> </Rectangle.RenderTransform> </Rectangle> <Rectangle Width="20" Height="4" > <Rectangle.Fill> <SolidColorBrush Color="Red"/> </Rectangle.Fill> <Rectangle.RenderTransform> <TransformGroup> <TranslateTransform X="10" Y="178"/> <RotateTransform CenterX="120" CenterY="180" Angle="135"/> </TransformGroup> </Rectangle.RenderTransform> </Rectangle> <Rectangle Width="20" Height="4" > <Rectangle.Fill> <SolidColorBrush Color="Red"/> </Rectangle.Fill> <Rectangle.RenderTransform> <TransformGroup> <TranslateTransform X="10" Y="178"/> <RotateTransform CenterX="120" CenterY="180" Angle="180"/> </TransformGroup> </Rectangle.RenderTransform> </Rectangle><!-- 目盛のアーチ --> <Path Stroke="Black" StrokeThickness="1" Canvas.Top="80" Canvas.Left="20"> <Path.Data> <PathGeometry> <PathGeometry.Figures> <PathFigure StartPoint="0,100"> <PathFigure.Segments> <ArcSegment Size="100,100" RotationAngle="-45" IsLargeArc="True" SweepDirection="Clockwise" Point="200,100"/> </PathFigure.Segments> </PathFigure> </PathGeometry.Figures> </PathGeometry> </Path.Data> </Path><!-- 目盛の数字だよ --> <TextBlock Text="0" FontSize="14"> <TextBlock.RenderTransform> <TranslateTransform X="30" Y="170"/> </TextBlock.RenderTransform> </TextBlock> <TextBlock Text="10" FontSize="14"> <TextBlock.RenderTransform> <TransformGroup> <TranslateTransform X="30" Y="170"/> <RotateTransform CenterX="120" CenterY="180" Angle="45"/> </TransformGroup> </TextBlock.RenderTransform> </TextBlock> <TextBlock Text="100" FontSize="14"> <TextBlock.RenderTransform> <TransformGroup> <TranslateTransform X="30" Y="170"/> <RotateTransform CenterX="120" CenterY="180" Angle="90"/> </TransformGroup> </TextBlock.RenderTransform> </TextBlock> <TextBlock Text="1000" FontSize="14"> <TextBlock.RenderTransform> <TransformGroup> <TranslateTransform X="30" Y="170"/> <RotateTransform CenterX="120" CenterY="180" Angle="135"/> </TransformGroup> </TextBlock.RenderTransform> </TextBlock> <TextBlock Text="10000" FontSize="14"> <TextBlock.RenderTransform> <TransformGroup> <TranslateTransform X="30" Y="170"/> <RotateTransform CenterX="120" CenterY="180" Angle="180"/> </TransformGroup> </TextBlock.RenderTransform> </TextBlock><!-- 針だよ --> <Path Stroke="Orange" StrokeThickness="1" Canvas.Top="75" Canvas.Left="115" Opacity="70"> <Path.Data> <PathGeometry> <PathGeometry.Figures> <PathFigure StartPoint="5,0"> <PathFigure.Segments> <LineSegment Point="0,110"/> <LineSegment Point="10,110"/> <LineSegment Point="5,0"/> </PathFigure.Segments> </PathFigure> </PathGeometry.Figures> <PathGeometry.Transform> <RotateTransform x:Name="indicatorRotation" Angle="-90" CenterX="5" CenterY="105"/> </PathGeometry.Transform> </PathGeometry> </Path.Data> <Path.Fill> <SolidColorBrush Color="Orange"/> </Path.Fill> </Path> </Canvas>
|
で、コードビハインドは、
public partial class RoundMeterPart : UserControl { public RoundMeterPart() { InitializeComponent(); } public string MeterTitle { get { return tbTitle.Text; } set { tbTitle.Text = value; } } public string MeterUnit { get { return tbUnit.Text; } set { tbUnit.Text = value; } } public double MeterValue { set { tbValue.Text = value.ToString(); double angle = -90; if (value > 1) { double lvalue = System.Math.Log10(value); angle += lvalue * 45; } indicatorRotation.Angle = angle; } } }
|
こんな感じ。これで、Meterプロパティに値をぶっこめば、対数化された値で針の角度が変わります。
でもこれだと、値を更新した時に針が飛び飛びに動いて、それっぽくないですね。それっぽくするためにアニメーションを活用します。
MeterValueプロパティのsetの実装を以下のように変えます。
public double MeterValue { set { tbValue.Text = value.ToString(); double angle = -90; if (value > 1) { double lvalue = System.Math.Log10(value); angle += lvalue * 45; } Duration duration = new Duration(TimeSpan.FromMilliseconds(500)); DoubleAnimation animation = new DoubleAnimation(angle, duration); indicatorRotation.BeginAnimation(RotateTransform.AngleProperty, animation); } }
|
こうすれば、古い値から新しい値の角度に滑らかに変わります。修正はたったの3行。ぱっと見、XAMLは煩雑だけど、あっという間に、らしい部品の出来上がりです。