列内のボタン、クリックイベントハンドラーでの元の行を取得


97

WPF Datagridのitemsourceを、DALから返されたオブジェクトのリストに設定しました。ボタンを含む追加の列も追加しました。xamlは次のとおりです。

<toolkit:DataGridTemplateColumn  MinWidth="100" Header="View">
    <toolkit:DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Button Click="Button_Click">View Details</Button>
        </DataTemplate>
    </toolkit:DataGridTemplateColumn.CellTemplate>
</toolkit:DataGridTemplateColumn>

これは問題なくレンダリングされます。しかし、Button_Clickメソッドでは、ボタンが存在するデータグリッドの行を取得する方法はありますか?より具体的には、私のオブジェクトのプロパティの1つは "Id"であり、これをイベントハンドラーの別のフォームのコンストラクターに渡すことができるようにしたいと考えています。

private void Button_Click(object sender, RoutedEventArgs e)
    {
        //I need to know which row this button is on so I can retrieve the "id"  
    }

おそらく、xamlに何か特別なものが必要なのでしょうか、それとも、これを迂回的にしようとしているのでしょうか?どんな助け/アドバイスもありがたいです。

回答:


128

基本的に、ボタンは行データオブジェクトのデータコンテキストを継承します。私はそれをMyObjectと呼んでいますが、MyObject.IDがあなたが望んでいたものであることを願っています。

private void Button_Click(object sender, RoutedEventArgs e)
{
    MyObject obj = ((FrameworkElement)sender).DataContext as MyObject;
    //Do whatever you wanted to do with MyObject.ID
}

7
この種のものを実行する理想的な方法は、コマンド(基本的にMVVMパターン)を使用することです。データオブジェクト(ViewModel)でコマンドを作成し、Button.Commandを呼び出すことができるので、ボタンクリックのようなコードはありません。
Jobi Joy

1
@JobiJoy:コマンド/ RelayCommandを使用したこの例はありますか?私はいくつかのことをしようとしていますが、仕事にそれを得ることができない...
VoodooChild

私が見たコマンド例の問題は、選択したデータグリッドのアイテムをビューモデルのメンバーにデータバインドする必要があるため、削除ボタンとして十分なコマンドを生成するのが難しいことです。アプリ内のほとんどすべてのものを削除するために使用できる、1つの削除ボタンテンプレート列リソースが必要です。
Eric

47

これを行うもう1つの方法は、IDをボタンのCommandParameterプロパティにバインドすることです。

<Button Click="Button_Click" CommandParameter="{Binding Path=ID}">View Details</Button>

次に、コードでそのようにアクセスできます。

private void Button_Click(object sender, RoutedEventArgs e)
{
    object ID = ((Button)sender).CommandParameter;
}

イベントとコマンドを混同しているのはなぜですか?コマンドを使用し、コマンドパラメーターを使用します。
ProfK 2016年

1
3つの答え:なぜそうしないのですか?シンプルさ。そしてOPは、コマンドではなくイベントハンドラについて質問しています。コマンドはやり過ぎかもしれません。使用するCommandParameterプロパティの使用目的ではないかもしれないが、意味的に、それはより多く使用するよりも有意義だTagとハンドラでバインドされたオブジェクトからIDを取得するよりも簡単。コマンドを使用する場合は、そのアプローチで問題ありませんが、使用しない場合は、なぜ複雑さを追加するのでしょうか。
xr280xr 2016年

10

コマンドパラメータDataContextにバインドしてJobi JoyのようにMVVMを尊重する別の方法は、ボタンがdatacontextフォーム行を継承すると言っています。

XAMLのボタン

<RadButton Content="..." Command="{Binding RowActionCommand}" 
                         CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}, Path=DataContext}"/>

コマンドの実装

public void Execute(object parameter)
    {
        if (parameter is MyObject)
        {

        }
    }

では、RowActionCommandはモデル内にあるのでしょうか、それともボタンのデータコンテキストをViewModelにリセットするのでしょうか。
Tom Padilla

@PetrŠebesta "RowActionCommandは各行ビューモデルで定義されています。" これは意味がありません。しかしとにかく、素晴らしい解決策。
Igor


0

DataGridのDataContextがDataViewオブジェクト(DataTableのDefaultViewプロパティ)の場合は、次のようにすることもできます。

private void Button_Click(object sender, RoutedEventArgs e) {
   DataRowView row = (DataRowView)((Button)e.Source).DataContext;
}

それはあるはずですe.OriginalSource。の代わりにe.Source
Bigeyes 2017年

真剣にBigeyes、私の答えは、実際のライブで動作するコードからです!
SurfingSanta 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.