Klicken Sie in einer Spalte auf die Schaltfläche, um die Zeile abzurufen, aus der sie im Click-Ereignishandler stammt

97

Ich habe die Elementquelle meines WPF-Datagrid auf eine Liste von Objekten festgelegt, die von meinem DAL zurückgegeben wurden. Ich habe auch eine zusätzliche Spalte hinzugefügt, die eine Schaltfläche enthält. Die xaml befindet sich unten.

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

Dies macht gut. Gibt es bei der Button_Click- Methode eine Möglichkeit, die Zeile in dem Datagrid abzurufen, in dem sich die Schaltfläche befindet? Insbesondere ist eine der Eigenschaften meiner Objekte "Id", und ich möchte dies an den Konstruktor eines anderen Formulars im Ereignishandler übergeben können.

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

Vielleicht brauche ich etwas extra in meinem xaml, oder vielleicht mache ich das auf Umwegen? Jede Hilfe / Beratung geschätzt.

RekrowYnapmoc
quelle

Antworten:

128

Grundsätzlich erbt Ihre Schaltfläche den Datenkontext eines Zeilendatenobjekts. Ich nenne es MyObject und hoffe, dass MyObject.ID das ist, was Sie wollten.

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
quelle
7
Der ideale Weg, um solche Dinge zu tun, ist die Verwendung von Befehlen (im Grunde MVVM-Muster). Sie können einen Befehl in Ihrem Datenobjekt (ViewModel) erstellen und Button.Command aufrufen, damit kein Code wie Button Click dahinter steckt.
Jobi Joy
1
@JobiJoy: Haben Sie ein Beispiel dafür mit einem Command / RelayCommand? Ich versuche einige Dinge, kann es aber nicht zum
Laufen bringen
Das Problem mit den Befehlsbeispielen, die ich gesehen habe, besteht darin, dass Sie das ausgewählte Element des Datagrids an ein Mitglied Ihres Ansichtsmodells binden müssen. Daher ist es schwierig, den Befehl so zu generieren, dass er für eine Schaltfläche zum Löschen geeignet ist. Ich möchte eine Spaltenressource für die Schaltfläche zum Löschen von Schaltflächen, mit der ich so ziemlich alles in meiner App löschen kann.
Eric
47

Eine andere Möglichkeit, dies zu tun, besteht darin, die ID an die CommandParameter-Eigenschaft der Schaltfläche zu binden:

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

Dann können Sie wie im Code darauf zugreifen:

private void Button_Click(object sender, RoutedEventArgs e)
{
    object ID = ((Button)sender).CommandParameter;
}
xr280xr
quelle
Warum verwechseln Sie Ereignisse und Befehle? Verwenden Sie einen Befehl und den darin enthaltenen Befehlsparameter.
ProfK
1
3 Antworten: Warum nicht? Einfachheit. Und das OP fragt nach Ereignishandlern, nicht nach Befehlen. Ein Befehl könnte übertrieben sein. Die Verwendung ist CommandParametermöglicherweise nicht die beabsichtigte Verwendung der Eigenschaft, aber semantisch gesehen ist sie sinnvoller als die Verwendung Tagund einfacher als das Abrufen der ID vom gebundenen Objekt im Handler. Wenn Sie Befehle bevorzugen, ist dieser Ansatz in Ordnung, aber warum sollten Sie die Komplexität erhöhen, wenn Sie ihn nicht verwenden?
xr280xr
10

Eine andere Möglichkeit, die an den Befehlsparameter DataContext gebunden ist und MVVM respektiert, wie Jobi Joy sagt, dass die Schaltfläche die Datenkontext-Formularzeile erbt.

Schaltfläche in XAML

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

Befehlsimplementierung

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

        }
    }
Petr Šebesta
quelle
Würde sich RowActionCommand im Modell befinden oder würden Sie den Datenkontext der Schaltfläche auf das ViewModel zurücksetzen?
Tom Padilla
@ PetrŠebesta "RowActionCommand ist in jedem Zeilenansichtsmodell definiert." Das macht keinen Sinn. Aber trotzdem schöne Lösung.
Igor
4
MyObject obj= (MyObject)((Button)e.Source).DataContext;
Shiha
quelle
0

Wenn der DataContext Ihres DataGrid ein DataView-Objekt ist (die DefaultView-Eigenschaft einer DataTable), können Sie Folgendes tun:

private void Button_Click(object sender, RoutedEventArgs e) {
   DataRowView row = (DataRowView)((Button)e.Source).DataContext;
}
SurfingSanta
quelle
Es sollte sein e.OriginalSource. statt e.Source.
Großaugen
Ernsthaft Bigeyes, meine Antwort stammt aus echtem, lebendigem, funktionierendem Code!
SurfingSanta