Pulsante in una colonna, ottenendo la riga da cui proviene sul gestore dell'evento Click


97

Ho impostato l'origine elementi del mio WPF Datagrid su un elenco di oggetti restituiti dal mio DAL. Ho anche aggiunto una colonna extra che contiene un pulsante, il xaml è sotto.

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

Questo rende bene. Tuttavia, con il metodo Button_Click , esiste un modo per ottenere la riga sul datagrid in cui risiede il pulsante? Più specificamente, una delle proprietà dei miei oggetti è "Id" e mi piacerebbe essere in grado di passarla al costruttore di un altro form nel gestore di eventi.

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

Forse ho bisogno di qualcosa in più nel mio xaml, o forse lo sto facendo in modo indiretto? Qualsiasi aiuto / consiglio apprezzato.

Risposte:


128

Fondamentalmente il tuo pulsante erediterà il datacontesto di un oggetto dati riga. Lo chiamo come MyObject e spero che MyObject.ID sia quello che volevi.

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
Il modo ideale per fare questo tipo di cose è usare i comandi (fondamentalmente pattern MVVM) puoi creare un comando nel tuo Data Object (ViewModel) e chiamare Button.Command, in modo che non ci sia alcun codice dietro come Button click.
Jobi Joy

1
@JobiJoy: ne hai un esempio usando un comando / comando relè? Sto provando poche cose ma non riesco a farlo funzionare ..
VoodooChild

Il problema con gli esempi di comandi che ho visto è che devi associare l'elemento selezionato datagrid a un membro del tuo modello di visualizzazione e quindi è difficile generare il comando abbastanza da essere valido per un pulsante Elimina. Voglio una risorsa colonna del modello di pulsante di eliminazione che posso utilizzare per eliminare praticamente qualsiasi cosa nella mia app.
Eric

47

Un altro modo in cui mi piace farlo è associare l'ID alla proprietà CommandParameter del pulsante:

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

Quindi puoi accedervi in ​​questo modo nel codice:

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

Perché confondi eventi e comandi? Usa un comando e usa il parametro di comando in esso.
ProfK

1
3 risposte: perché no? Semplicità. E l'OP chiede informazioni sui gestori di eventi, non sui comandi. Un comando potrebbe essere eccessivo. L'utilizzo CommandParameterpotrebbe non essere l'uso previsto della proprietà, ma semanticamente è più significativo dell'utilizzo Tage più semplice del recupero dell'ID dall'oggetto associato nel gestore. Se preferisci i comandi, questo approccio va bene, ma perché aggiungere la complessità se non lo userai?
xr280xr

10

Un altro modo che si lega al parametro di comando DataContext e rispetta MVVM come Jobi Joy dice che il pulsante eredita la riga del modulo datacontext.

Pulsante in XAML

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

Implementazione del comando

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

        }
    }

Quindi, RowActionCommand sarebbe nel Model o reimposteresti il ​​datacontesto del pulsante al ViewModel?
Tom Padilla

@ PetrŠebesta "RowActionCommand è definito in ogni modello di visualizzazione riga." Questo non ha alcun senso. Ma comunque, bella soluzione.
Igor

4
MyObject obj= (MyObject)((Button)e.Source).DataContext;

0

Se il DataContext del tuo DataGrid è un oggetto DataView (la proprietà DefaultView di un DataTable), puoi anche fare questo:

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

Dovrebbe essere e.OriginalSource. invece di e.Source.
Occhi grandi

Scherzi a parte Bigeyes, la mia risposta è da codice reale, live, funzionante!
SurfingSanta
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.