SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

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

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

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

コマンドで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パターンの実装方法は多様で、実際の業務アプリケーションでは、もっと複雑な処理が必要となりますが、本記事での基本的な実装紹介が開発の一助となれば幸いです。

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
現役エンジニア直伝! 「現場」で使えるコンポーネント活用術(SPREAD)連載記事一覧

もっと読む

この記事の著者

グレープシティ株式会社 SPREADチーム(グレープシティカブシキガイシャ スプレッドチーム)

 宮城県仙台市に本社を構えるグレープシティでは、日本の業務に適したシステムをより早く開発するためのソフトウェアを提供しています。エンドユーザーの利用しやすさ、幅広いユーザー環境への対応、そして何よりプログラマの作業を軽減することを一番に目指しています。 SPREADは、ExcelライクなUIを実現するグリッドコンポーネントの定番として、日本のみならず全世界で数多くの開発者に利用されている製品。同チームはWindows Forms、ASP.NET、WPFといった.NET向け製品のほか、HTML...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/10195 2017/05/30 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング