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は煩雑だけど