Tombol di kolom, mendapatkan baris asalnya pada event handler Click

97

Saya telah mengatur itemsource dari WPF Datagrid saya ke Daftar Objek yang dikembalikan dari DAL saya. Saya juga menambahkan kolom tambahan yang berisi tombol, xaml di bawah.

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

Ini membuatnya baik-baik saja. Namun pada metode Button_Click , adakah cara agar saya bisa mendapatkan baris di datagrid tempat tombol berada? Lebih khusus lagi, salah satu properti objek saya adalah "Id", dan saya ingin meneruskan ini ke konstruktor formulir lain di event handler.

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

Mungkin saya membutuhkan sesuatu yang ekstra di xaml saya, atau mungkin saya akan melakukannya secara tidak langsung? Setiap bantuan / saran dihargai.

RekrowYnapmoc
sumber

Jawaban:

128

Pada dasarnya tombol Anda akan mewarisi konteks data dari objek data baris. Saya menyebutnya sebagai MyObject dan berharap MyObject.ID adalah yang Anda inginkan.

private void Button_Click(object sender, RoutedEventArgs e)
{
    MyObject obj = ((FrameworkElement)sender).DataContext as MyObject;
    //Do whatever you wanted to do with MyObject.ID
}
Joy Jobi
sumber
7
Cara ideal untuk melakukan hal semacam ini adalah dengan menggunakan perintah (Pada dasarnya pola MVVM) Anda dapat membuat perintah di Objek Data (ViewModel) dan memanggil Button.Command, sehingga tidak akan ada kode di belakang seperti klik Tombol.
Jobi Joy
1
@ JobiJoy: apakah Anda memiliki contoh ini menggunakan Command / RelayCommand? Saya mencoba beberapa hal tetapi tidak bisa membuatnya bekerja ..
VoodooChild
Masalah dengan contoh perintah yang saya lihat adalah bahwa Anda harus mengikat data item yang dipilih datagrid ke anggota model tampilan Anda dan oleh karena itu sulit untuk menghasilkan perintah yang cukup baik untuk tombol hapus. Saya ingin satu sumber daya kolom template tombol hapus yang dapat saya gunakan untuk menghapus hampir semua hal di aplikasi saya.
Eric
47

Cara lain yang saya suka untuk melakukan ini adalah dengan mengikat ID ke properti CommandParameter tombol:

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

Kemudian Anda dapat mengaksesnya seperti itu dalam kode:

private void Button_Click(object sender, RoutedEventArgs e)
{
    object ID = ((Button)sender).CommandParameter;
}
xr280xr
sumber
Mengapa Anda mencampur acara dan perintah? Gunakan Command dan gunakan parameter perintah di dalamnya.
ProfK
1
3 jawaban: Mengapa tidak? Kesederhanaan. Dan OP menanyakan tentang event handler, bukan perintah. Perintah mungkin berlebihan. Penggunaan CommandParametermungkin bukan tujuan penggunaan properti, tetapi secara semantik, ini lebih berarti daripada menggunakan Tagdan lebih sederhana daripada mengambil ID dari objek terikat di handler. Jika Anda lebih suka Perintah, pendekatan itu baik-baik saja, tetapi mengapa menambahkan kompleksitas jika Anda tidak akan menggunakannya?
xr280xr
10

Cara lain yang mengikat ke parameter perintah DataContext dan menghormati MVVM seperti Jobi Joy mengatakan tombol mewarisi baris formulir datacontext.

Tombol di XAML

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

Implementasi perintah

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

        }
    }
Petr Šebesta
sumber
Jadi, apakah RowActionCommand akan berada dalam Model atau apakah Anda akan menyetel ulang konteks data tombol ke ViewModel?
Tom Padilla
@ PetrŠebesta "RowActionCommand ditentukan dalam setiap model tampilan baris." Ini tidak masuk akal. Tapi bagaimanapun, solusi yang bagus.
Igor
4
MyObject obj= (MyObject)((Button)e.Source).DataContext;
Shiha
sumber
0

Jika DataGrid's DataContext Anda adalah objek DataView (properti DefaultView dari DataTable), Anda juga bisa melakukan ini:

private void Button_Click(object sender, RoutedEventArgs e) {
   DataRowView row = (DataRowView)((Button)e.Source).DataContext;
}
SurfingSanta
sumber
Seharusnya begitu e.OriginalSource. bukannya e.Source.
Bigeyes
Serius Bigeyes, jawaban saya adalah dari kode nyata, langsung, dan berfungsi!
SurfingSanta