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は煩雑だけど、あっという間に、らしい部品の出来上がりです。
Comments (0)

Skip to main content