Silverlight と WPF を対象とする Infragistics XamDataChart では、バインドした項目のプロパティに基づいてマーカーの外観が異なるシリーズを作成できます。

ScatterSeries、RangeColumnSeries などの MarkerSeries で MarkerTemplate プロパティを使用することができます。UI 要素のプロパティが項目の DataContext プロパティにバインドされるカスタム DataTemplate を作成できます。

<DataTemplate x:Key="bubbleTemplate" >

    <Ellipse Stretch="Fill"

               HorizontalAlignment="Stretch"

               VerticalAlignment="Stretch"

               StrokeThickness="0.5"

               MinWidth="10" MinHeight="10"

               Width="{Binding Item.Width}"

               Height="{Binding Item.Width}">

        <ToolTipService.ToolTip>

            <StackPanel Orientation="Vertical">

                <TextBlock Text="{Binding Item.YValue, StringFormat='Value: {0}'}" />

            </StackPanel>

        </ToolTipService.ToolTip>

    </Ellipse>

</DataTemplate>

RgbValueConverter は、数値を連続色パレットの SolidColorBrush に変換します。

項目の DataContext の値に基づいてマーカーの色を変更する場合があります。値は別のタイプが可能です。値を指定したタイプから特定の色の Brush に変換するために ValueConverter が必要です。

この記事では 数値型から個別の色パレットに変換、または数値型から連続色パレットに変換する 2 種類のコンバーターを紹介します。

サンプル アプリケーションでは Silverlight を対象としています。WPF の XamDataChart を使用すると、同じように WPF アプリケーションを作成できます。

サンプルアプリケーション作成の要件:

ソフトウェア:

  • Visual Studio 2010
  • NetAdvantage for Silverlight Data Visualization (このサンプルは 2010.2 バージョン) の Infragistics XamMap コンポーネント

作成手順:

 Silverlight の場合:

  • Silverlight アプリケーションを作成します。
  • ValueConverter を作成します。NumberToBrush は数値から個別の色パレットの Brush に変換します。RgbValueConverter は数値から連続色パレットの Brush に変換します。ほとんどのコンポーネントでは Background、Stroke などのプロパティで Brush が使用されます。
  • XamDataChart の DataContext で使用されるサンプル データを作成します。
  • 丸を表す MarkerTemplate を作成します。色は YValue プロパティにバインドされます。ここでは 2 つのコンバーターを使用します。
  • 作成した MarkerTemplate 定義を使用して、散布図シリーズの XamDataChart を作成します。
  • サンプル アプリケーションを実行します。

1. Visual Studio 2010 で Silverlight アプリケーションを作成します。

2. 2 つの ValueConverter を追加します。

NumberToBrush は数値 (double 型) を SolidColorBrush に変換します。Brush は個別の色パレットから取得される色です。パレットには 6 つの SolidColorBrush があります。色は白い、赤い、オレンジ、黄色、緑、と青です。パラメーターであるため、範囲があり、コンバーターは数値に相対する SolidColorBrush を返します。値が範囲外にある場合、白い SolidColorBrush を返します。

public sealed class NumberToBrush : IValueConverter

{

 

    private Brush[] _brushes = new Brush[] { new SolidColorBrush(Colors.White),

                                            new SolidColorBrush(Colors.Red),

                                            new SolidColorBrush(Colors.Orange),

                                            new SolidColorBrush(Colors.Yellow),

                                            new SolidColorBrush(Colors.Green),

                                            new SolidColorBrush(Colors.Blue)};

 

    #region Property Accessors

 

    public Brush[] Brushes

    {

        get { return this._brushes; }

        set { this._brushes = value; }

    }

 

    #endregion

 

    #region IValueConverter

 

    public object Convert(object value, Type targetType, object parameter,

        System.Globalization.CultureInfo culture)

    {

 

        if ((typeof(Brush) != targetType || typeof(double) != value.GetType()))

        {

            return null;

        }

 

        Range range = parameter as Range;

        if(range == null)

        {

            range = new Range();

            range.Min = 0;

            range.Max = 10;

        }

 

        var i = (double)value;

 

        double interval = (double)(range.Max - range.Min)/(_brushes.Length - 1);

        int index = (int)(i / interval + 0.5);

 

        if (index <= 0 || index >= this._brushes.Length) return this._brushes[0];

 

        return this._brushes[index];

    }

 

    public object ConvertBack(object value, Type targetType, object parameter,

        System.Globalization.CultureInfo culture)

    {

        throw new NotImplementedException();

    }

 

    #endregion

}

 

public class Range : BaseViewModel

{

    #region Min

 

    private int _min;

    public int Min

    {

        get { return this._min; }

        set

        {

            this._min = value;

            OnPropertyChanged("Min");

        }

    }

 

    #endregion // Min

 

    #region Max

 

    private int _max;

    public int Max

    {

        get { return this._max; }

        set

        {

            this._max = value;

            OnPropertyChanged("Max");

        }

    }

 

    #endregion // Max

 

}

コンバーターは HSV (Hue-Saturation-Value) を使用します。

http://ja.wikipedia.org/wiki/HSV%E8%89%B2%E7%A9%BA%E9%96%93

詳細について、Wikipedia リンクを参照してください。

RgbValueConverter では、数値は Min と Max 値の範囲内で正規化されます。

var normValue = i * 360/(range.Max – range.Min);

RgbValueConverter のコードは以下です。

public sealed class RgbValueConverter : IValueConverter

{

 

    private static Color ColorFromHsv(double hue, double saturation, double value)

    {

        int hi = (int)(Math.Floor(hue / 60)) % 6;

        double f = hue / 60 - Math.Floor(hue / 60);

 

        value = value * 255;

        int v = (int)(value);

        int p = (int)(value * (1 - saturation));

        int q = (int)(value * (1 - f * saturation));

        int t = (int)(value * (1 - (1 - f) * saturation));

 

        if (hi == 0)

        {

            return Color.FromArgb(255, (byte)v, (byte)t, (byte)p);

        }

 

        if (hi == 1)

        {

            return Color.FromArgb(255, (byte)q, (byte)v, (byte)p);

        }

 

        if (hi == 2)

        {

            return Color.FromArgb(255, (byte)p, (byte)v, (byte)t);

        }

 

        if (hi == 3)

        {

            return Color.FromArgb(255, (byte)p, (byte)q, (byte)v);

        }

 

        if (hi == 4)

        {

            return Color.FromArgb(255, (byte)t, (byte)p, (byte)v);

        }

 

        return Color.FromArgb(255, (byte)v, (byte)p, (byte)q);

    }

 

 

    #region IValueConverter

 

    public object Convert(object value, Type targetType, object parameter,

        System.Globalization.CultureInfo culture)

    {

 

        if ((typeof(Brush) != targetType || typeof(double) != value.GetType()))

        {

            return null;

        }

 

        Range range = parameter as Range;

        if(range == null)

        {

            range = new Range();

            range.Min = 0;

            range.Max = 10;

        }

 

        var i = System.Convert.ToDouble(value);

 

        if (i <= range.Min || range.Min >= range.Max)

        {               

            return new SolidColorBrush(Colors.White);

        }

 

        var normValue = i * 360/(range.Max - range.Min);

 

        return new SolidColorBrush(ColorFromHsv(normValue, 1, 1));

 

    }

 

    public object ConvertBack(object value, Type targetType, object parameter,

        System.Globalization.CultureInfo culture)

    {

        throw new NotImplementedException();

    }

 

    #endregion

 

}

3. XamDataChart の DataContext で使用されるサンプル データを作成します。

public class BubbleDataCollection

        : ObservableCollection<BubblePoint>

{

 

    public BubbleDataCollection()

    {

        this.Add(new BubblePoint { XValue = 4, YValue = 10, Width = 30 });

        this.Add(new BubblePoint { XValue = 4, YValue = 4, Width = 40 });

        this.Add(new BubblePoint { XValue = 8, YValue = 8, Width = 20 });

        this.Add(new BubblePoint { XValue = 10, YValue = 1, Width = 50 });

        this.Add(new BubblePoint { XValue = 1, YValue = 10, Width = 40 });

    }

 

}

 

public class BubblePoint

{

    public double XValue { get; set; }

    public double YValue { get; set; }

    public double Width { get; set; }

}
    <UserControl.Resources>

        ...

        <XamDataChartCustomTemplatesDemo:BubbleDataCollection x:Key="bubbleCollection" />

       ....

    <Grid x:Name="LayoutRoot" Background="White" DataContext="{StaticResource bubbleCollection}">

4. 丸を表す MarkerTemplate を作成します。色は YValue プロパティにバインドされます。ここでは 2 つのコンバーターを使用します。

<UserControl.Resources>

    <Converters:NumberToBrush x:Key="indexToBrush"/>

    <Converters:RgbValueConverter x:Key="RgbToBrush"/>

    <XamDataChartCustomTemplatesDemo:BubbleDataCollection x:Key="bubbleCollection" />

    <Converters:Range x:Key="range" Min="0" Max="10"/>

    <DataTemplate x:Key="bubbleTemplate" >

        <Ellipse Stretch="Fill"

                   HorizontalAlignment="Stretch"

                   VerticalAlignment="Stretch"

                   Fill="{Binding Item.YValue, Converter={StaticResource indexToBrush}, ConverterParameter={StaticResource range}}"

                   Stroke="{Binding Series.ActualMarkerOutline}"

                   StrokeThickness="0.5"

                   MinWidth="10" MinHeight="10"

                   Width="{Binding Item.Width}"

                   Height="{Binding Item.Width}">

            <ToolTipService.ToolTip>

                <StackPanel Orientation="Vertical">

                    <TextBlock Text="{Binding Item.YValue, StringFormat='Value: {0}'}" />

                </StackPanel>

            </ToolTipService.ToolTip>

        </Ellipse>

    </DataTemplate>

    <DataTemplate x:Key="bubbleTemplate2" >

        <Ellipse Stretch="Fill"

                   HorizontalAlignment="Stretch"

                   VerticalAlignment="Stretch"

                   Fill="{Binding Item.YValue, Converter={StaticResource RgbToBrush}, ConverterParameter={StaticResource range}}"

                   Stroke="{Binding Series.ActualMarkerOutline}"

                   StrokeThickness="0.5"

                   MinWidth="10" MinHeight="10"

                   Width="{Binding Item.Width}"

                   Height="{Binding Item.Width}">

            <ToolTipService.ToolTip>

                <StackPanel Orientation="Vertical">

                    <TextBlock Text="{Binding Item.YValue, StringFormat='Value: {0}'}" />

                </StackPanel>

            </ToolTipService.ToolTip>

        </Ellipse>

    </DataTemplate>       

</UserControl.Resources>

MarkerTemplate 定義は BubblePoint オブジェクトの YValue に基づいて Brush で塗りつぶされた楕円を含みます。

5. 作成した MarkerTemplate 定義を使用して、散布図シリーズの XamDataChart を作成します。

<igChart:XamDataChart x:Name="theChart">

    <igChart:XamDataChart.Axes>

        <igChart:NumericXAxis x:Name="xAxis"

                               MinimumValue="0" MaximumValue="15"/>

        <igChart:NumericYAxis x:Name="yAxis"

                               MinimumValue="0" MaximumValue="15"/>

    </igChart:XamDataChart.Axes>

 

    <igChart:XamDataChart.Series>

        <igChart:ScatterSeries x:Name="scatter"

                               MarkerTemplate="{StaticResource bubbleTemplate}"

                               ItemsSource="{Binding}"

                               XMemberPath="XValue"

                               YMemberPath="YValue"

                               XAxis="{Binding ElementName=xAxis}"

                               YAxis="{Binding ElementName=yAxis}"></igChart:ScatterSeries>

    </igChart:XamDataChart.Series>

</igChart:XamDataChart>

...

<igChart:XamDataChart x:Name="theChart2">

    <igChart:XamDataChart.Axes>

        <igChart:NumericXAxis x:Name="xAxis2"

                                   MinimumValue="0" MaximumValue="15"/>

        <igChart:NumericYAxis x:Name="yAxis2"

                                   MinimumValue="0" MaximumValue="15"/>

    </igChart:XamDataChart.Axes>

 

    <igChart:XamDataChart.Series>

        <igChart:ScatterSeries x:Name="scatter2"

                                   MarkerTemplate="{StaticResource bubbleTemplate2}"

                                   ItemsSource="{Binding}"

                                   XMemberPath="XValue"

                                   YMemberPath="YValue"

                                   XAxis="{Binding ElementName=xAxis2}"

                                   YAxis="{Binding ElementName=yAxis2}"></igChart:ScatterSeries>

    </igChart:XamDataChart.Series>

 

</igChart:XamDataChart>

6. アプリケーションを実行します。

Tagged:

製品について

Ultimate UI for WPF