デフォルトの XamRadialGauge では、目盛りの数値ラベルは画像のように水平な角度できれいに並んでいます。これはこれで視認性もよく見やすいのですが、数値ラベルの確度を変えてもっとスポーティな表現にしたいこともありますね。

XamRadialGauge では残念ながら数値ラベルの確度をスポーツモードに仕上げる機能が実装されておりません。少し手間ではありますが、数値ラベル(TextBlock)を回転させてあげることで、エレガントなスポーツモードに仕上げることができちゃいます!

今回の完成イメージはこちらです。

実装方法を見ていきましょう

今回は、XamRadialGauge の LayoutUpdated イベントをトリガーに動作するように実装してみました。

メインとなるイベント処理

private void xamRadialGauge1_LayoutUpdated(object sender, EventArgs e)
{
    IEnumerable<TextBlock> list = FindVisualChildren<TextBlock>(xamRadialGauge1);

    foreach (TextBlock tb in list)
    {
        // TextBlock のテキストを整数に変換する(テキストが数値であることが前提)
        int val = Int32.Parse(tb.Text);

        // 回転角度
        double angle = 0;

        if (val == 0 || val == 50 || val == 100)
        {
            // val が 0, 50, 100 の場合は回転させない
            angle = 0;
        }
        else if (val >= 10 && val <= 40)
        {
            // val が 10, 20, 30, 40 の場合は正の方向に18度ずつ大きくなるように回転
            int multiplier = val / 10; // 1, 2, 3, 4 になる
            angle = multiplier * 18;
        }
        else if (val >= 60 && val <= 90)
        {
            // val が 60, 70, 80, 90 の場合は負の方向に18度ずつ小さくなるように回転
            int multiplier = (100 - val) / 10; // 4, 3, 2, 1 になる
            angle = -(multiplier * 18);
        }
        // 👆ここまでは適宜設定したい角度に合わせて実装してください!

     // 👇 今回主に使いたいのは以下より下のコードです。

        // TextBlock の中心点を設定 (回転の基準を中央にする) 
        tb.RenderTransformOrigin = new Point(.5, .5);

        // 計算した角度で TextBlock を回転させる
        RotateTransform rotateTransform1 = new RotateTransform(angle);
        tb.RenderTransform = rotateTransform1;
    }
}

子要素を探して取得するためのメソッドです。

メインのイベント処理で使います。

// このメソッドは、与えられた親要素(dependencyObject)の中にある
// 指定された型(ここでは TextBlock)の子要素をすべて見つけるための再帰メソッドです。
// 例えば、Canvas の中にある TextBlock や他の UI 要素を検索するために使います。
IEnumerable<T> FindVisualChildren<T>(DependencyObject dependencyObject) where T : DependencyObject
{
    // もし親要素が null の場合は、処理をやめます。
    if (dependencyObject == null)
        yield break;

    // 現在の要素が指定された型 T (ここでは TextBlock)である場合、それを返します。
    if (dependencyObject is T)
        yield return (T)dependencyObject;

    // 親要素に含まれる子要素を再帰的に調べます。
    // 子要素が複数存在する場合でも、すべての子要素を調べていきます。
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(dependencyObject); i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(dependencyObject, i);
        foreach (T childOfChild in FindVisualChildren<T>(child))
        {
            yield return childOfChild;
        }
    }
}

以上です!実際に動作するサンプルを GitHub にご用意しておりますので是非お試し下さい。

(まずは半円にしたいよ。という方はこちらの KB コンテンツをどうぞ)

Tagged:

製品について

Ultimate UI for WPF