いつも、センサー、センサー、云うてますやん。データ計測したら見たいですやん。…という事で、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は煩雑だけど、あっという