XamDataGrid でデータを選択するとそれに連動して XamDataChart の方もハイライトされるサンプルの作り方の紹介です。

実現イメージ

画面左側に置いている XamDataGrid のデータを選択すると、画面右側の XamDataChart の対応するデータがハイライトされるアプリケーションを作っていきます。

実装概要

  1. ColumnSeries を Series の中で最背面になるように重ね、それをハイライト用に使用します。
  2. Model 側にハイライト用のプロパティを持たせ、ハイライト用の ColumnSeries の ValueMemberPath に指定します。
  3. ViewModel 側でハイライト用の初期値データを作ります。
  4. ViewModel のハイライト用のデータを XamDataChart の ColumnSeries にバインドします。
  5. XamDataGrid にも XamDataChart にバインドするのと同じデータをバインドします。
  6. XamDataGrid でレコードの単一選択を有効化し、セルのクリックでそのレコードが選択されるようにします。
  7. XamDataGrid の SelectedDataItem を ViewModel 側のプロパティとバインドします。
  8. XamDataGrid の SelectedDataItem のプロパティ値が変更されたタイミングで ViewModel 側でハイライト用のデータを更新します。
  9. ViewModel 側の Y 軸の最小値と最大値を View 側の XamDataChart の Y 軸にバインドします。

実装詳細

1. ColumnSeries を Series の中で最背面になるように重ね、それをハイライト用に使用します。

XamDataChart の Seriesコレクションに最初に追加することでシリーズの中で最背面に配置することができます。さらに半透明の色を割り当てればハイライトさせたような見た目になります。

<!-- MainWindow.xaml -->

<ig:XamDataChart ...>

    <!-- ... (中略) ... -->

    <ig:XamDataChart.Series>

        <!--
            ハイライト用の ColumnSeries。
            XamDataChart の Series コレクションに最初に追加することでシリーズの中で最背面に配置することができます。
            さらに半透明の色を割り当てればハイライトさせたような見た目になります。
        -->
        <ig:ColumnSeries
            x:Name="columnSeriesForHighlight"
            MarkerType="None"
            Outline="Transparent" ...>
            <ig:ColumnSeries.Brush>
                <SolidColorBrush Color="Blue" Opacity="0.25"/>
            </ig:ColumnSeries.Brush>
        </ig:ColumnSeries>

        <ig:StepLineSeries ... />
        <ig:StepLineSeries .../>

        <!-- ... (中略) ... -->

    </ig:XamDataChart.Series>
</ig:XamDataChart>

2. Model 側にハイライト用のプロパティを持たせ、ハイライト用の ColumnSeries の ValueMemberPath に指定します。

Model 側に XamDataChart にバインドするデータのクラスを定義し、さらにハイライト用のデータを持たせるプロパティを追加します。プロパティ名は何でもよいのですが、今回はデータ本体のプロパティ名が Amount1、Amount2 ですので、それにならって AmountForHighlight としてみます。

// SampleChartDataItem.cs

internal class SampleChartDataItem : ObservableObject
{
    private String _yearLabel = "";
    public String YearLabel
    {
        get { return _yearLabel; }
        set { _yearLabel = value; OnPropertyChanged(); }
    }

    // StepLineSeries 1 つめのデータです。
    private int _amount1;
    public int Amount1
    {
        get { return _amount1; }
        set { _amount1 = value; OnPropertyChanged(); }
    }

    // StepLineSeries 2 つめのデータです。
    private int _amount2;
    public int Amount2
    {
        get { return _amount2; }
        set { _amount2 = value; OnPropertyChanged(); }
    }

    // ハイライト用のデータです。
    private int _amountForHighlight;
    public int AmountForHighlight
    {
        get { return _amountForHighlight; }
        set { _amountForHighlight = value; OnPropertyChanged(); }
    }

    public SampleChartDataItem()
    {
    }
}

この AmountForHighlight を XamDataChart のハイライト用の ColumnSeries の ValueMemberPath に指定します。

<!-- MainWindow.xaml -->

<!-- ... (中略) ... -->

<ig:XamDataChart.Series>

    <!--
        ハイライト用の ColumnSeries。
        XamDataChart の Series コレクションに最初に追加することでシリーズの中で最背面に配置することができます。
        さらに半透明の色を割り当てればハイライトさせたような見た目になります。
        そのうえで、ハイライト用のプロパティ (AmountForHighlight) を ValueMemberPath として設定ます。
    -->
    <ig:ColumnSeries
        x:Name="columnSeriesForHighlight"
        ValueMemberPath="AmountForHighlight"
        MarkerType="None"
        Outline="Transparent" ...>
        <ig:ColumnSeries.Brush>
            <SolidColorBrush Color="Blue" Opacity="0.25"/>
        </ig:ColumnSeries.Brush>
    </ig:ColumnSeries>

    <ig:StepLineSeries ... />
    <ig:StepLineSeries .../>

    <!-- ... (中略) ... -->

</ig:XamDataChart.Series>

<!-- ... (中略) ... -->

3. ViewModel 側でハイライト用の初期値データを作ります。

ハイライト用のデータは ColumnSeries にバインドされます。値が Y 軸の最小値であれば ColumnSeries の縦棒は表示されませんし、最大値であれば Y 軸いっぱいに表示されます。

今回はこの性質を利用します。「実現イメージ」にある通り Y 軸の最小値は 0 なのでハイライト用のデータの初期値を 0 とします。

// MainWindowViewModel.cs

internal class MainWindowViewModel : ObservableObject
{
    private ObservableCollection<SampleChartDataItem> _sampeChartData;
    public ObservableCollection<SampleChartDataItem> SampleChartData
    {
        get { return _sampeChartData; }
        set { _sampeChartData = value; OnPropertyChanged(); }
    }

    // Y軸の最少値
    private int _minimumY = 0;

    public MainWindowViewModel()
    {
        _sampeChartData = new ()
        {
            new () { YearLabel = "1998", Amount1 = 162, Amount2 = 93, AmountForHighlight = _minimumY },
            new () { YearLabel = "1999", Amount1 = 57, Amount2 = 140, AmountForHighlight = _minimumY },
            new () { YearLabel = "2000", Amount1 = 92, Amount2 = 134, AmountForHighlight = _minimumY },
            new () { YearLabel = "2001", Amount1 = 105, Amount2 = 74, AmountForHighlight = _minimumY },
            new () { YearLabel = "2002", Amount1 = 81, Amount2 = 89, AmountForHighlight = _minimumY },
        };
    }
}

4. ViewModel のハイライト用のデータを XamDataChart の ColumnSeries にバインドします。

ColumnSeries の ItemsSource プロパティに ViewModel の SampleChartData プロパティをバインドします。

<!-- MainWindow.xaml -->

<!-- ... (中略) ... -->

<ig:XamDataChart.Series>

    <!--
        ハイライト用の ColumnSeries。
        XamDataChart の Series コレクションに最初に追加することでシリーズの中で最背面に配置することができます。
        さらに半透明の色を割り当てればハイライトさせたような見た目になります。
        そのうえで、ハイライト用のプロパティ (AmountForHighlight) を ValueMemberPath として設定ます。
    -->
    <ig:ColumnSeries
        x:Name="columnSeriesForHighlight"
        ItemsSource="{Binding SampleChartData}"
        ValueMemberPath="AmountForHighlight"
        MarkerType="None"
        Outline="Transparent" ...>
        <ig:ColumnSeries.Brush>
            <SolidColorBrush Color="Blue" Opacity="0.25"/>
        </ig:ColumnSeries.Brush>
    </ig:ColumnSeries>

    <ig:StepLineSeries ... />
    <ig:StepLineSeries .../>

    <!-- ... (中略) ... -->

</ig:XamDataChart.Series>

<!-- ... (中略) ... -->

5. XamDataGrid にも XamDataChart にバインドするのと同じデータをバインドします。

XamDataGrid の DataSource プロパティに ViewModel の SampleChartData プロパティをバインドします。

「実現イメージ」にある通り今回 XamDataGrid に表示するのは「Year」のデータだけですので、列自動生成の機能は無効にし (AutoGenerateFields=”False”)、FieldLayout の Fields プロパティには YearLabel のField のみを追加します。

<!-- MainWindow.xaml -->

<igDP:XamDataGrid
    x:Name="xamDataGrid1"
    DataSource="{Binding SampleChartData}" ...>
    <igDP:XamDataGrid.FieldLayoutSettings>
        <igDP:FieldLayoutSettings AutoGenerateFields="False" />
    </igDP:XamDataGrid.FieldLayoutSettings>

    <!-- ... (中略) ... -->

    <igDP:XamDataGrid.FieldLayouts>
        <igDP:FieldLayout>
            <igDP:FieldLayout.Fields>
                <igDP:Field Name="YearLabel" Label="Year" Width="100"/>
            </igDP:FieldLayout.Fields>
        </igDP:FieldLayout>
    </igDP:XamDataGrid.FieldLayouts>
</igDP:XamDataGrid>

6. XamDataGrid でレコードの単一選択を有効化し、セルのクリックでそのレコードが選択されるようにします。

レコードの単一選択の有効化は FieldLayoutSettings オブジェクトの SelectionTypeRecord プロパティに “Single” を指定することでできます。

またセルクリック時の既定の動作は「編集モードに入る」です。そうではなく、クリックしたレコードが選択されるように、FieldSettings オブジェクトの CellClickAction プロパティに “SelectRecord” を指定します。

<!-- MainWindow.xaml -->

<igDP:XamDataGrid
    x:Name="xamDataGrid1"
    DataSource="{Binding SampleChartData}" ...>
    <igDP:XamDataGrid.FieldLayoutSettings>
        <igDP:FieldLayoutSettings
            AutoGenerateFields="False"
            SelectionTypeRecord="Single" />
    </igDP:XamDataGrid.FieldLayoutSettings>
    <igDP:XamDataGrid.FieldSettings>
        <igDP:FieldSettings CellClickAction="SelectRecord"/>
    </igDP:XamDataGrid.FieldSettings>
    <igDP:XamDataGrid.FieldLayouts>
        <igDP:FieldLayout>
            <igDP:FieldLayout.Fields>
                <igDP:Field Name="YearLabel" Label="Year" Width="100"/>
            </igDP:FieldLayout.Fields>
        </igDP:FieldLayout>
    </igDP:XamDataGrid.FieldLayouts>
</igDP:XamDataGrid>

7. XamDataGrid の SelectedDataItem を ViewModel 側のプロパティとバインドします。

View 側では XamDataGrid の SelectedDataItem プロパティを ViewModel 側の SelectedDataItem プロパティとバインドします。

<!-- MainWindow.xaml -->

<igDP:XamDataGrid
    x:Name="xamDataGrid1"
    DataSource="{Binding SampleChartData}"
    SelectedDataItem="{Binding SelectedDataItem}">
    <igDP:XamDataGrid.FieldLayoutSettings>
        <igDP:FieldLayoutSettings AutoGenerateFields="False" SelectionTypeRecord="Single" />
    </igDP:XamDataGrid.FieldLayoutSettings>
    <igDP:XamDataGrid.FieldSettings>
        <igDP:FieldSettings CellClickAction="SelectRecord"/>
    </igDP:XamDataGrid.FieldSettings>
    <igDP:XamDataGrid.FieldLayouts>
        <igDP:FieldLayout>
            <igDP:FieldLayout.Fields>
                <igDP:Field Name="YearLabel" Label="Year" Width="100"/>
            </igDP:FieldLayout.Fields>
        </igDP:FieldLayout>
    </igDP:XamDataGrid.FieldLayouts>
</igDP:XamDataGrid>

ViewModel 側に SampleDataItem 型の SelectedDataItem プロパティを追加します。

// MainWindowViewModel.cs

internal class MainWindowViewModel : ObservableObject
{
    private ObservableCollection<SampleChartDataItem> _sampeChartData;
    public ObservableCollection<SampleChartDataItem> SampleChartData
    {
        get { return _sampeChartData; }
        set { _sampeChartData = value; OnPropertyChanged(); }
    }

    // Y軸の最少値
    private int _minimumY = 0;

    // XamDataGridで選択されているデータ項目を設定・取得するプロパティ
    private SampleChartDataItem? _selectedDataItem = null;
    public SampleChartDataItem? SelectedDataItem
    {
        get { return _selectedDataItem; }
        set
        {
            _selectedDataItem = value;
            OnPropertyChanged();
        }
    }

    public MainWindowViewModel()
    {
        _sampeChartData = new ()
        {
            new () { YearLabel = "1998", Amount1 = 162, Amount2 = 93, AmountForHighlight = _minimumY },
            new () { YearLabel = "1999", Amount1 = 57, Amount2 = 140, AmountForHighlight = _minimumY },
            new () { YearLabel = "2000", Amount1 = 92, Amount2 = 134, AmountForHighlight = _minimumY },
            new () { YearLabel = "2001", Amount1 = 105, Amount2 = 74, AmountForHighlight = _minimumY },
            new () { YearLabel = "2002", Amount1 = 81, Amount2 = 89, AmountForHighlight = _minimumY },
        };
    }
}

8. ViewModel 側で SelectedDataItem のプロパティ値が変更されたタイミングでハイライト用のデータを更新します。

SelectedDataItem プロパティの setter の中で、_selectedDataItem と一致する SampleChartDataItem オブジェクトについてはハイライト用の AmountForHighlight プロパティに Y 軸の最大値を設定し、そうでない場合は Y 軸の最小値を設定します。

// MainWindowViewModel.cs

internal class MainWindowViewModel : ObservableObject
{
    private ObservableCollection<SampleChartDataItem> _sampeChartData;
    public ObservableCollection<SampleChartDataItem> SampleChartData
    {
        get { return _sampeChartData; }
        set { _sampeChartData = value; OnPropertyChanged(); }
    }

    // Y軸の最大値
    private int _maximumY = 200;

    // Y軸の最少値
    private int _minimumY = 0;

    // XamDataGridで選択されているデータ項目を設定・取得するプロパティ
    private SampleChartDataItem? _selectedDataItem = null;
    public SampleChartDataItem? SelectedDataItem
    {
        get { return _selectedDataItem; }
        set
        {
            if (_selectedDataItem != value)
            {
                _selectedDataItem = value;
                OnPropertyChanged();

                foreach (var chartDataItem in SampleChartData)
                {
                    if (_selectedDataItem != null && chartDataItem.YearLabel == _selectedDataItem.YearLabel)
                    {
                        chartDataItem.AmountForHighlight = _maximumY;
                    }
                    else
                    {
                        chartDataItem.AmountForHighlight = _minimumY;
                    }
                }
            }
        }
    }

    public MainWindowViewModel()
    {
        _sampeChartData = new ()
        {
            new () { YearLabel = "1998", Amount1 = 162, Amount2 = 93, AmountForHighlight = _minimumY },
            new () { YearLabel = "1999", Amount1 = 57, Amount2 = 140, AmountForHighlight = _minimumY },
            new () { YearLabel = "2000", Amount1 = 92, Amount2 = 134, AmountForHighlight = _minimumY },
            new () { YearLabel = "2001", Amount1 = 105, Amount2 = 74, AmountForHighlight = _minimumY },
            new () { YearLabel = "2002", Amount1 = 81, Amount2 = 89, AmountForHighlight = _minimumY },
        };
    }
}

AmountForHighlight プロパティの値が変更されると、SampleChartDataItem クラス側で変更通知が発火し、View 側に変更が通知され、AmountForHighlight プロパティを監視している XamDataChart のハイライト用の ColumnSeries が更新されます。これにより、XamDataGrid でデータを選択するとそれに連動して XamDataChart 側もハイライトするデータが更新される、という動作が実現されています。

9. ViewModel 側の Y 軸の最小値と最大値を View 側の XamDataChart の Y 軸にバインドします。

ViewModel 側に _minimumY と _maximumY の各フィールド変数と紐づいたプロパティを追加します。

// MainWindowViewModel.cs

internal class MainWindowViewModel : ObservableObject
{
    private ObservableCollection<SampleChartDataItem> _sampeChartData;
    public ObservableCollection<SampleChartDataItem> SampleChartData
    {
        get { return _sampeChartData; }
        set { _sampeChartData = value; OnPropertyChanged(); }
    }

    // Y軸の最大値を設定・取得するプロパティ
    private int _maximumY = 200;
    public int MaximumY
    {
        get { return _maximumY; }
        set { _maximumY = value; OnPropertyChanged(); }
    }

    // Y軸の最少値を設定・取得するプロパティ
    private int _minimumY = 0;
    public int MinimumY
    {
        get { return _minimumY; }
        set { _minimumY = value; OnPropertyChanged(); }
    }

    // XamDataGridで選択されているデータ項目を設定・取得するプロパティ
    private SampleChartDataItem? _selectedDataItem = null;
    public SampleChartDataItem? SelectedDataItem
    {
        get { return _selectedDataItem; }
        set
        {
            if (_selectedDataItem != value)
            {
                _selectedDataItem = value;
                OnPropertyChanged();

                foreach (var chartDataItem in SampleChartData)
                {
                    if (_selectedDataItem != null && chartDataItem.YearLabel == _selectedDataItem.YearLabel)
                    {
                        chartDataItem.AmountForHighlight = _maximumY;
                    }
                    else
                    {
                        chartDataItem.AmountForHighlight = _minimumY;
                    }
                }
            }
        }
    }

    public MainWindowViewModel()
    {
        _sampeChartData = new ()
        {
            new () { YearLabel = "1998", Amount1 = 162, Amount2 = 93, AmountForHighlight = _minimumY },
            new () { YearLabel = "1999", Amount1 = 57, Amount2 = 140, AmountForHighlight = _minimumY },
            new () { YearLabel = "2000", Amount1 = 92, Amount2 = 134, AmountForHighlight = _minimumY },
            new () { YearLabel = "2001", Amount1 = 105, Amount2 = 74, AmountForHighlight = _minimumY },
            new () { YearLabel = "2002", Amount1 = 81, Amount2 = 89, AmountForHighlight = _minimumY },
        };
    }
}

XamDataChart の NumericYAxis オブジェクトの MinimumValue プロパティ、MaximumValue プロパティに ViewModel 側の対応するプロパティをバインドします。そしてハイライト用の ColumnSeries オブジェクトの YAxis プロパティに Y 軸を設定します。

<!-- MainWindow.xaml -->

<ig:XamDataChart
    x:Name="xamDataChart1" ...>
    <ig:XamDataChart.Axes>
        <ig:CategoryXAxis x:Name="xAxis1" ItemsSource="{Binding SampleChartData}" Label="{}{YearLabel}"/>
        <ig:NumericYAxis x:Name="yAxis1" MinimumValue="{Binding MinimumY}" MaximumValue="{Binding MaximumY}"/>
    </ig:XamDataChart.Axes>

    <ig:XamDataChart.Series>

        <!--
        ハイライト用の ColumnSeries。
        XamDataChart の Series コレクションに最初に追加することでシリーズの中で最背面に配置することができます。
        さらに半透明の色を割り当てればハイライトさせたような見た目になります。
        そのうえで、ハイライト用のプロパティ (AmountForHighlight) を ValueMemberPath として設定します。
        -->
        <ig:ColumnSeries
            x:Name="columnSeriesForHighlight"
            ItemsSource="{Binding SampleChartData}"
            XAxis="{Binding ElementName=xAxis1}"
            YAxis="{Binding ElementName=yAxis1}"
            ValueMemberPath="AmountForHighlight"
            MarkerType="None"
            Outline="Transparent">
            <ig:ColumnSeries.Brush>
                <SolidColorBrush Color="Blue" Opacity="0.25"/>
            </ig:ColumnSeries.Brush>
        </ig:ColumnSeries>

        <ig:StepLineSeries ... />
        <ig:StepLineSeries ... />
    </ig:XamDataChart.Series>

</ig:XamDataChart>

 

以上で完成です!

 

 

製品について

Ultimate UI for WPF