引き続き、Microsoft.TeamFoundation.MVVM
名前空間を使って作る、WPFアプリの話です。
WPFのDataGridにボタンを表示し、そのボタンを押すと選択行に対して
- 行データの更新
- 行データを元にした、メッセージボックスの表示や子Windowの表示
を行うようなアプリを試してみました。
2015/12/10 追記 ここから
公式Blogに以下の記事が掲載されましたので、Microsoft.TeamFoundation.MVVM
の使用前に記事を確認してみてください。
Microsoft.TeamFoundation.MVVM 名前空間の利用について - Visual Studio サポート チーム blog - Site Home - MSDN Blogs
2015/12/10 追記 ここまで
環境
作成イメージ
親Window
呼ばれる子Window
数量加算ボタンを押した後に、Windowボタンを押した結果
親Window
View
DataGridButtonMainView.xamlに実装します。
Microsoft.TeamFoundation.MVVM名前空間を使った子Windowの表示設定
前回と同じく、Window要素に必要なものを追加します。
<Window x:Class="DataGridMVVM.DataGridButtonMainView" ... xmlns:local="clr-namespace:DataGridMVVM" xmlns:mvvm="clr-namespace:Microsoft.TeamFoundation.MVVM;assembly=Microsoft.TeamFoundation.Controls" mvvm:MVVMSupport.ViewModel="{Binding}" ...> <Window.DataContext> <local:DataGridButtonMainViewModel/> </Window.DataContext> <Window.Resources> <mvvm:RegisterWindow x:Key="SubWindowKey" Type="local:DataGridButtonSubView"/> </Window.Resources> </Window>
DataGridのデータソースと現在行へのデータバインディング設定
データソースはItemsSource
に、現在行はSelectedItem
に、それぞれ設定します。
実際には、上記のDataContextに指定したViewModelのプロパティをPathに設定します。
参考:Get selected row item in DataGrid WPF - Stack Overflow
<DataGrid ItemsSource="{Binding UpdateSourceTrigger=PropertyChanged, Path=DataGrid}" SelectedItem="{Binding Path=CurrentRowItem}"> </DataGrid>
DataGridのボタン
DataGridの各行にボタンを表示するには、 <DataGridTemplateColumn>
を使います。
参考:[C#, WPF] datagrid にボタン配置 - パイナップルの芯
Commandへのデータバインディングはいつもと同じですが、DataGrid内では
- Pathに、
DataContext.<ViewModelのプロパティ>
- RelativeSourceに、
{RelativeSource AncestorType={x:Type DataGrid}}}
と指定することが異なります。
参考:mvvm - Firing a RelayCommand from a button inside a WPF DataGrid - Stack Overflow
<DataGridTemplateColumn> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Button Command="{Binding Path=DataContext.ShowWindowCommand, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" .../> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn>
なお、RelativeSourceについては、以下が参考になりました。
- RelativeSource のマークアップ拡張機能 - MSDN
- 【WPF】RelativeSource - 亀岡的プログラマ日記
- Q092. Binding.RelativeSource の使い方がよくわからない - 憂国のプログラマ Hatena版
ちなみに、参考先にはFindAncestor
の記述がありますが、手元のインテリセンスには表示されてこなかったので、XAMLには書いてありません。
ViewModel
DataGridButtonMainViewModel.csに実装します。
特に変わったところはなく、
Microsoft.TeamFoundation.MVVM.ViewModelBase
を継承- Viewのデータバインディングで指定したプロパティを記述
- DataGrid内ButtonのCommand向けの、
public ICommand ShowWindowCommand
プロパティ - RelayCommandで指定する
private void ExecuteShowMessageCommand()
メソッド - ItemSource向けの、
public ObservableCollection<Order> DataGrid
プロパティ - SelectedItem向けの、
public Order CurrentRowItem
プロパティ
- DataGrid内ButtonのCommand向けの、
を実装します。
また、Execute<hoge>Command()
メソッドは3種類ありますが、それぞれ以下のコードを実装してあります。
子Window表示
親Windowのデータは、子WindowのViewModelのプロパティへ渡しました。
private void ExecuteShowWindowCommand() { var vm = new DataGridButtonSubViewModel(); vm.ItemName = CurrentRowItem.ItemName; vm.Quantity = CurrentRowItem.Quantity; WindowDisplayService.ShowDialog("SubWindowKey", vm); }
MessageBox表示
private void ExecuteShowMessageCommand() { if (CurrentRowItem == null) return; // CurrentRowItemはOrder型であり、Order型でToString()メソッドをオーバーライドしてある MessageBoxService.Show(CurrentRowItem.ToString()); }
現在行の数量を加算
private void ExecuteAddQuantityCommand() { if (CurrentRowItem == null) return; // Model(Order型)のメソッドで加算 CurrentRowItem.AddQuantity(); }
Model
Order.csに
- DataGridの
ItemsSource
やSelectedItem
で必要になるプロパティ INotifyPropertyChanged
インタフェースの実装- ViewModelから呼ばれる
AddQuantity()
メソッドや、ToString()
メソッドのオーバーライド
を実装します。
特に変わったことはないので、コードは省略します。
子Window
DataGridButtonSubView.xamlや DataGridButtonSubViewModel.csなどに実装しますが、特に変わったことはないので、コードは省略します。
ソースコード
GitHubにあげておきました。
CSharp-Sample/MVVMApp/DataGridMVVM at master · thinkAmi/CSharp-Sample