次の方法で共有


データグリッド上のボタンにイベントを追加する方法

質問

2013年6月17日月曜日 4:57 | 1 票

こんにちは。

タイトルの内容なのですが、練習でMVVMを利用したプログラムを作成しています。

その中で、データグリッド内にボタンを追加して、ボタンが押された時のClickイベントでDelegateCommandで用意したメソッドを実行させようとしているのですが、うまく動きません。

ちなみに、通常のボタンだとDelegateCommandはうまく動いていました。

なので、DataContentにViewModelを与えてから、グリッド内が作成させる。そこでようやくボタンが画面上に出てくる関係で、うまくCommandと紐付いていないような気がするのですが、根本的に考え違いがあるのでしょうか?

以上、よろしくお願いします。

<DataGrid Name="ViewGrid" Grid.Row="1" Style="{StaticResource Modan}" ItemsSource="{Binding Pages}" Width="400" AutoGenerateColumns="False" IsReadOnly="True" SelectionMode="Single" >
<DataGrid.Columns>
    <DataGridTextColumn Width="2*" Header="種別" Binding="{Binding Group}" />
    <DataGridTextColumn Width="3*" Header="項目名" Binding="{Binding Name}" />
    <DataGridTextColumn Width="1*" Header="閲覧" Binding="{Binding Authority}" />
    <DataGridTemplateColumn Header="" Width="2*">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <Button Content="選択" Command="{Binding OnSelectView}" CommandParameter="{Binding SelectedItem, ElementName=ViewGrid}" Margin="-1" />
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
public DelegateCommand OnSelectView
        {
            get
            {
                if (this._onSelectView == null) this._onSelectView = new DelegateCommand(ExecuteOnSelectView);
                return this._onSelectView;
            }

        }


        private void ExecuteOnSelectView(object parameter)
        {
            MessageBox.Show("a");
        }

環境

windows 7 pro x32

VisualStudioExpress2012 for windows desktop

すべての返信 (2)

2013年6月17日月曜日 6:10 ✅回答済み | 2 票

もう少しソースを見せていただかないとはっきりわかりませんが、以下のことに注意して確認してみて下さい。
DataGridの各行にバインドしている明細それぞれが、暗黙的にDataGridの各行のDataContextになります。よって、OnSelectViewと単に書いた場合、各行にバインドしている明細の中からOnSelectViewコマンドを探すことになります。一方で、RelativeSourceでDataGridを探し、そのDataContext.OnSelectViewと書いた場合は、DataGridのDataContextプロパティのOnSelectViewということになります。このページのDataContextとしてViewModelを設定しており、DataGridのDataContextを明に指定していないのであれば、DataGridのDataContextはページのDataContextと一致することになります。よって、ViewModelの中からOnSelectViewを探すことになります。
ポイントとしては、DataGridの各行のDataContextはViewModelになっておらず、それぞれの明細オブジェクトがDataContextになっているということです。

★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/


2013年6月17日月曜日 5:26

すいません。いろいろ調べていたら、次のように修正することで、うまくイベントが繋がるようになりました。

ただ、よくわからないのがCommand側は{Binding DataContent.On***}としたことです。このDataContentは何を指しているのでしょうか? このXAMLファイルPageならPageのDataContentになるのでしょうか。

また、なぜこの箇所だけこういった記述にルールが変わったのか理解しきれていません。何が原因でDataContent.***と書かないとつながらないようになっていたのでしょうか?

<DataGrid Grid.Row="1" Style="{StaticResource Modan}" ItemsSource="{Binding Pages}" Width="400" AutoGenerateColumns="False" IsReadOnly="True" SelectionMode="Single" >
                <DataGrid.Columns>
                    <DataGridTextColumn Width="2*" Header="種別" Binding="{Binding Group}" />
                    <DataGridTextColumn Width="3*" Header="項目名" Binding="{Binding Name}" />
                    <DataGridTextColumn Width="1*" Header="閲覧" Binding="{Binding Authority}" />
                    <DataGridTemplateColumn Header="" Width="2*">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Button Content="選択" Command="{Binding DataContext.OnSelectView, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" Margin="-1" />
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
            </DataGrid>

参考

binding command