Shoeisha Technology Media

CodeZine(コードジン)

記事種別から探す

SPREAD for WPFでMVVMパターンのアプリケーションを作成する

  • LINEで送る
  • このエントリーをはてなブックマークに追加
目次

コマンドでSPREADを操作する

 SPREADの行、列、セルを生成するRow、Column、Cellクラスのメンバは、依存関係プロパティを持っていません。そのため、これらのクラスのメンバをバインディングターゲットとすることができず、ビューモデルからセルや列に対して直接バインディングができません。しかし、ボタン型セルに設定したコマンドが実行されると、Executeメソッドのパラメータからは、セルの情報を保存したCellCommandParameterオブジェクトを取得できます。また、コマンドクラスにSPREADオブジェクトを示すプロパティを追加することで、コマンドによりSPREADを操作できるようになります。ここでは、そのテクニックについて紹介します。

 「値段」ボタン型セルのクリックで、4列目に値段を表示し、さらに値段が300円以上の場合は、行の背景色を変更するというコマンドを作成します。

コマンドを変更する

 先ほど作成したGetPriceCommandクラスを変更します。GcSpreadGridオブジェクトを示すプロパティを追加します。

VB.NET(ProductViewModel.vb)
Private _spread As GcSpreadGrid
Public Property spread As GcSpreadGrid
    Get
        Return _spread
    End Get
    Set(value As GcSpreadGrid)
        _spread = value
    End Set
End Property
C#(ProductViewModel.cs)
private GcSpreadGrid _spread;
public GcSpreadGrid spread
{
    get { return _spread; }
    set { _spread = value; }
}

 次に、Executeメソッドを変更します。パラメータ「parameter」から、ボタンが押されたセル情報を格納しているCellCommandParameterクラスを取得できます。CellCommandParameterクラスのCellPositionプロパティからボタンが押されたセルの行インデックスを取得できるため、変更を行いたいSPREADの行にアクセスすることができます。

VB.NET(ProductViewModel.vb)
Public Sub Execute(parameter As Object) Implements ICommand.Execute
    ' CustomCommandParameterに指定したProductViewModelオブジェクトを取得します。
    Dim cp As CellCommandParameter = parameter
    Dim viewModel As ProductViewModel = cp.CustomCommandParameter

    ' ビューモデルのプロパティを更新します。
    viewModel.ProductName = viewModel.SelectedProduct.Name
    viewModel.ProductPrice = viewModel.SelectedProduct.Price

    ' ボタン型セルの右側のセルに価格を表示します。
    _spread(cp.CellPosition.Row, cp.CellPosition.Column + 1).Value = viewModel.SelectedProduct.Price

    If _spread IsNot Nothing Then
        ' ボタン型セルの右側のセルに価格を表示します。
        _spread(cp.CellPosition.Row, cp.CellPosition.Column + 1).Value = viewModel.SelectedProduct.Price

        ' 価格が300円以上のものは、行の背景色を変更します。
        If viewModel.SelectedProduct.Price > 300 Then
            _spread.Rows(cp.CellPosition.Row).Background = Brushes.Pink
        End If
    End If
End Sub
C#(ProductViewModel.cs)
public void Execute(object parameter)
{
    // CustomCommandParameterに指定したProductViewModelオブジェクトを取得します。
    CellCommandParameter cp = parameter as CellCommandParameter;
    ProductViewModel viewModel = cp.CustomCommandParameter as ProductViewModel;

    // ビューモデルのプロパティを更新します。
    viewModel.ProductName = viewModel.SelectedProduct.Name;
    viewModel.ProductPrice = viewModel.SelectedProduct.Price;

if (_spread != null)
    {
        // ボタン型セルの右側のセルに価格を表示します。
        _spread[cp.CellPosition.Row, cp.CellPosition.Column + 1].Value = viewModel.SelectedProduct.Price;

        // 価格が300円以上のものは、行の背景色を変更します。
        if (viewModel.SelectedProduct.Price > 300)
        {
            _spread.Rows[cp.CellPosition.Row].Background = Brushes.Pink;
        }
        else
        {
            _spread.Rows[cp.CellPosition.Row].Background = Brushes.White;
        }
    }
}

 最後に、ビューでボタン型セルを生成するとき、Commandプロパティに設定するGetPriceCommandオブジェクトのspreadプロパティにGcSpreadGridオブジェクトを設定します。

VB.NET(MainWindow.xaml.vb)
' ボタン型セルを作成します。
Dim Button As New ButtonCellType()
Button.Content = "値段"
' ボタンにコマンドを設定します。
Button.Command = New GetPriceCommand() With {.spread = GcSpreadGrid1}
Button.CustomCommandParameter = viewModel
GcSpreadGrid1.Columns(2).CellType = Button
C#(MainWindow.xaml.cs)
// ボタン型セルを作成します。
ButtonCellType button = new ButtonCellType();
button.Content = "値段";
// ボタンにコマンドを設定します。
button.Command = new GetPriceCommand() { spread = gcSpreadGrid1 };
button.CustomCommandParameter = viewModel;
gcSpreadGrid1.Columns[2].CellType = button;

 XAMLでは、リソースとして定義したコマンドを次のように実装します。

XAML(MainWindow.xaml)
<Window.Resources>
    <local:GetPriceCommand x:Key="getPriceCommand" spread="{x:Reference gcSpreadGrid1}"  />
</Window.Resources>

 アプリケーションを実行し、いくつかボタン型セルをクリックすると、次のような結果となります。

コマンドでSPREADを操作
コマンドでSPREADを操作

コマンドのコンストラクタ引数を使用する

 コマンドクラスから、ビューモデルやSPREADオブジェクトへアクセスする方法として、CustomCommandParameterプロパティの使用や、コマンドクラスへのプロパティ追加を紹介しましたが、この他に、コマンドクラスのコンストラクタ引数にオブジェクトを渡す方法も考えられます。ただし、XAMLにはコンストラクタに引数を渡す方法が用意されていないため、この方法はコードビハインドでの設定のみ有効です。まず、コマンドを定義するGetPriceCommandクラスを次のように実装します。

VB.NET(ProductViewModel.vb)
Public Class GetPriceCommand
    Implements ICommand

    ' SPREADとビューモデルを示すプロパティを定義します。
    Private _spread As GcSpreadGrid
    Private _viewModel As ProductViewModel

    ' 引数付きコンストラクタ
    Public Sub New(ByRef spread As GcSpreadGrid, ByVal viewModel As ProductViewModel)
        _spread = spread
        _viewModel = viewModel
    End Sub

    Public Event CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged

    Public Function CanExecute(parameter As Object) As Boolean Implements ICommand.CanExecute
        Return True
    End Function

    Public Sub Execute(parameter As Object) Implements ICommand.Execute
        Dim cp As CellCommandParameter = parameter

        ' ビューモデルのプロパティを更新します。
        _viewModel.ProductName = _viewModel.SelectedProduct.Name
        _viewModel.ProductPrice = _viewModel.SelectedProduct.Price

        ' ボタン型セルの右側のセルに価格を表示します。
        _spread(cp.CellPosition.Row, cp.CellPosition.Column + 1).Value = _viewModel.SelectedProduct.Price

        ' 価格が300円以上のものは、行の背景色を変更します。
        If _viewModel.SelectedProduct.Price > 300 Then
            _spread.Rows(cp.CellPosition.Row).Background = Brushes.Pink
        End If
    End Sub
End Class
C#(ProductViewModel.cs)
public class GetPriceCommand : ICommand
{
    public event EventHandler CanExecuteChanged;

    // SPREADとビューモデルを示すプロパティを定義します。
    private GcSpreadGrid _spread;
    private ProductViewModel _viewModel;

    // 引数付きコンストラクタ
    public GetPriceCommand(GcSpreadGrid spread, ProductViewModel viewModel)
    {
        _spread = spread;
        _viewModel = viewModel;
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        CellCommandParameter cp = parameter as CellCommandParameter;

        //ビューモデルのプロパティを更新します。
        _viewModel.ProductName = _viewModel.SelectedProduct.Name;
        _viewModel.ProductPrice = _viewModel.SelectedProduct.Price;

        // ボタン型セルの右側のセルに価格を表示します。
        _spread[cp.CellPosition.Row, cp.CellPosition.Column + 1].Value = _viewModel.SelectedProduct.Price;

        // 価格が300円以上のものは、行の背景色を変更します。
        if (_viewModel.SelectedProduct.Price > 300)
        {
            _spread.Rows[cp.CellPosition.Row].Background = Brushes.Pink;
        }
        else
        {
            _spread.Rows[cp.CellPosition.Row].Background = Brushes.White;
        }
    }
}

 ビュー側のボタン型セルの設定は、以下の通りです。Commandプロパティに設定するGetPriceCommandクラスのコンストラクタ引数に、SPREADオブジェクトとビューモデルのオブジェクトを渡します。

VB.NET(MainWindow.xaml.vb)
' ボタン型セルを作成します。
Dim Button As New ButtonCellType()
Button.Content = "値段"
' ボタンにコマンドを設定します。
Button.Command = New GetPriceCommand(GcSpreadGrid1, viewModel)
GcSpreadGrid1.Columns(2).CellType = Button
C#(MainWindow.xaml.cs)
// ボタン型セルを作成します。
ButtonCellType button = new ButtonCellType();
button.Content = "値段";
// ボタンにコマンドを設定します。
button.Command = new GetPriceCommand(gcSpreadGrid1, viewModel);
gcSpreadGrid1.Columns[2].CellType = button;

 以上で、前項と同様の動作を実現することができます。

まとめ

 本記事では、SPREAD for WPFを使用して、シンプルなMVVMアプリケーションを作成する方法を紹介しました。SPREAD for WPFは、グリッドでありながら標準のDataGridやListBoxコントロールと異なり、ItemTemplateを持たないため、セルや行といった項目単位でバインディングすることができません。しかし、SPREADの持つ機能を利用して工夫することで、さまざまなコマンドを実装することも可能です。MVVMパターンの実装方法は多様で、実際の業務アプリケーションでは、もっと複雑な処理が必要となりますが、本記事での基本的な実装紹介が開発の一助となれば幸いです。



  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

バックナンバー

連載:現役エンジニア直伝! 「現場」で使えるコンポーネント活用術(SPREAD)

もっと読む

All contents copyright © 2005-2017 Shoeisha Co., Ltd. All rights reserved. ver.1.5