Przycisk w kolumnie pobierający wiersz, z którego pochodzi, do modułu obsługi zdarzeń Click

97

Ustawiłem itemsource mojego WPF Datagrid na listę obiektów zwróconych z mojego DAL. Dodałem również dodatkową kolumnę, która zawiera przycisk, Xaml znajduje się poniżej.

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

To sprawia, że ​​dobrze. Jednak w metodzie Button_Click jest jakiś sposób, aby uzyskać wiersz w datagrid, w którym znajduje się przycisk? Mówiąc dokładniej, jedną z właściwości moich obiektów jest „Id” i chciałbym móc przekazać ją do konstruktora innej formy w programie obsługi zdarzeń.

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

Może potrzebuję czegoś dodatkowego w moim xaml, a może zajmuję się tym okrężną drogą? Każda pomoc / rada mile widziana.

RekrowYnapmoc
źródło

Odpowiedzi:

128

Zasadniczo twój przycisk odziedziczy kontekst danych obiektu danych wiersza. Nazywam to MyObject i mam nadzieję, że MyObject.ID jest tym, czego chciałeś.

private void Button_Click(object sender, RoutedEventArgs e)
{
    MyObject obj = ((FrameworkElement)sender).DataContext as MyObject;
    //Do whatever you wanted to do with MyObject.ID
}
Jobi Joy
źródło
7
Idealnym sposobem na zrobienie tego rodzaju rzeczy jest użycie poleceń (w zasadzie wzorzec MVVM), możesz utworzyć polecenie w obiekcie danych (ViewModel) i wywołać Button.Command, aby nie było żadnego kodu za kliknięciem przycisku.
Jobi Joy
1
@JobiJoy: czy masz przykład tego przy użyciu polecenia / RelayCommand? Próbuję kilku rzeczy, ale nie mogę zmusić go do pracy ..
VoodooChild
Problem z przykładami poleceń, które widziałem, polega na tym, że musisz powiązać datagrid wybrany element z elementem modelu widoku, a zatem trudno jest uogólnić polecenie wystarczająco, aby było dobre dla przycisku usuwania. Chcę jednego zasobu kolumny szablonu przycisku usuwania, którego mogę użyć do usunięcia prawie wszystkiego z mojej aplikacji.
Eric
47

Innym sposobem, w jaki lubię to zrobić, jest powiązanie ID z właściwością CommandParameter przycisku:

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

Następnie możesz uzyskać do niego dostęp w ten sposób w kodzie:

private void Button_Click(object sender, RoutedEventArgs e)
{
    object ID = ((Button)sender).CommandParameter;
}
xr280xr
źródło
Dlaczego mylisz zdarzenia i polecenia? Użyj polecenia i użyj w nim parametru polecenia.
ProfK
1
3 odpowiedzi: Dlaczego nie? Prostota. OP pyta o programy obsługi zdarzeń, a nie polecenia. Polecenie może być przesadą. Używanie CommandParametermoże nie być zamierzonym przeznaczeniem właściwości, ale semantycznie jest bardziej znaczące niż używanie Tagi prostsze niż pobieranie identyfikatora z powiązanego obiektu w procedurze obsługi. Jeśli wolisz polecenia, to podejście jest w porządku, ale po co dodawać złożoność, jeśli nie zamierzasz go używać?
xr280xr
10

Inny sposób, który wiąże się z parametrem polecenia DataContext i szanuje MVVM, jak Jobi Joy mówi, że przycisk dziedziczy wiersz formularza kontekstu danych.

Przycisk w XAML

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

Wdrażanie poleceń

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

        }
    }
Petr Šebesta
źródło
Czy więc RowActionCommand będzie w modelu, czy może zresetujesz kontekst danych przycisku do ViewModel?
Tom Padilla
@ PetrŠebesta "RowActionCommand jest zdefiniowane w każdym modelu widoku wierszy." To nie ma sensu. W każdym razie fajne rozwiązanie.
Igor
4
MyObject obj= (MyObject)((Button)e.Source).DataContext;
Shiha
źródło
0

Jeśli DataContext Twojego DataGrid jest obiektem DataView (właściwość DefaultView elementu DataTable), możesz również zrobić to:

private void Button_Click(object sender, RoutedEventArgs e) {
   DataRowView row = (DataRowView)((Button)e.Source).DataContext;
}
SurfingSanta
źródło
Tak powinno być e.OriginalSource. zamiast e.Source.
Bigeyes
Poważnie Bigeyes, moja odpowiedź pochodzi z prawdziwego, działającego kodu!
SurfingSanta,