2009-03-24 4 views
32

Ich möchte den Benutzer aktivieren markieren Sie eine Zeile auf dem WPF DataGrid und drücken Sie die Löschtaste, um die Zeile zu löschen.Was ist das Ereignis "delete key gedrückt" für das WPF DataGrid?

  • Die Funktionalität ist bereits in die UI gebaut des Gitters, also dem Benutzer, die Zeile verschwindet
  • I handhaben diese aktuell den Selection Ereignis (Code unten)
  • I loop durch alle "e.RemovedItems" und löschen Sie sie mit LINQ

Problem ist: auch wenn Sie einfach se lect eine Zeile und bewegen Sie sich davon weg, Auswahl Änderung ausgelöst wird und diese Zeile ist in e.RemovedItems (was ist seltsam, warum würde einfach etwas auswählen es in einem RemovedItems-Container?).

So suche ich nach einem DeleteKeyPressed Ereignis, damit ich einfach damit umgehen kann. Wie heißt dieses Ereignis?

Ich benutze das Toolkit vom März 2009.

XAML:

<Grid DockPanel.Dock="Bottom"> 
    <toolkit:DataGrid x:Name="TheDataGrid" 
         SelectionChanged="TheDataGrid_SelectionChanged" 
         AutoGenerateColumns="True" 
         RowEditEnding="TheDataGrid_RowEditEnding"/> 

Code-Behind:

private void TheDataGrid_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) 
{ 
    if (e.RemovedItems.Count > 0) 
    { 
     Message.Text = "The following were removed: "; 
     foreach (object obj in e.RemovedItems) 
     { 
      Customer customer = obj as Customer; 
      Message.Text += customer.ContactName + ","; 
      _db.Order_Details.DeleteAllOnSubmit(
       customer.Orders.SelectMany(o => o.Order_Details)); 
      _db.Orders.DeleteAllOnSubmit(customer.Orders); 
      _db.Customers.DeleteOnSubmit(customer); 
     } 
    } 

    try 
    { 
     _db.SubmitChanges(); 
    } 
    catch (Exception ex) 
    { 
     Message.Text = ex.Message; 
    } 
} 

ANTWORT:

Dank lnferis, das war genau das, was ich suchte, hier ist mein fertig gelöschtes Ereignis Beachten Sie, dass das KeyDown-Ereignis für das Datagrid aus irgendeinem Grund nicht ausgelöst wird.

XAML:

<toolkit:DataGrid x:Name="TheDataGrid" 
        KeyDown="TheDataGrid_KeyDown" 
        PreviewKeyDown="TheDataGrid_PreviewKeyDown" 
        AutoGenerateColumns="True" 
        RowEditEnding="TheDataGrid_RowEditEnding"/> 

Code-behind

private void TheDataGrid_PreviewKeyDown(object sender, KeyEventArgs e) 
{ 
    if (e.Key == Key.Delete) 
    { 
     var grid = (DataGrid)sender; 

     if (grid.SelectedItems.Count > 0) 
     { 
      string checkMessage = "The following will be removed: "; 

      foreach (var row in grid.SelectedItems) 
      { 
       Customer customer = row as Customer; 
       checkMessage += customer.ContactName + ","; 
      } 
      checkMessage = Regex.Replace(checkMessage, ",$", ""); 

      var result = MessageBox.Show(checkMessage, "Delete", MessageBoxButton.OKCancel); 
      if (result == MessageBoxResult.OK) 
      { 
       foreach (var row in grid.SelectedItems) 
       { 
        Customer customer = row as Customer; 
        _db.Order_Details.DeleteAllOnSubmit(
         customer.Orders.SelectMany(o => o.Order_Details)); 
        _db.Orders.DeleteAllOnSubmit(customer.Orders); 
        _db.Customers.DeleteOnSubmit(customer); 
       } 
       _db.SubmitChanges(); 
      } 
      else 
      { 
       foreach (var row in grid.SelectedItems) 
       { 
        Customer customer = row as Customer; 
        LoadData(); 
        _db.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues, customer); //TODO: this doesn't refresh the datagrid like the other instance in this code 
       } 
      } 
     } 
    } 
} 

private void TheDataGrid_KeyDown(object sender, KeyEventArgs e) 
{ 
    Console.WriteLine("never gets here for some reason"); 
} 
+3

Die KeyDown sollte nie hier ankommen, weil es bereits Handler ist (e.Handled = true) in der vorherigen Handler in der Blase. – Shimmy

Antwort

25

Die RemovedItems Artikel spiegeln die aus der Auswahl entfernt Elemente, und nicht vom Netz.

Behandeln Sie das PreviewKeyDown Ereignis, und verwenden Sie die SelectedItems Eigenschaft die ausgewählten Zeilen dort zu löschen:

private void PreviewKeyDownHandler(object sender, KeyEventArgs e) { 
    var grid = (DataGrid)sender; 
    if (Key.Delete == e.Key) { 
     foreach (var row in grid.SelectedItems) { 
      ... // perform linq stuff to delete here 
     } 
    } 
} 
+3

Gibt es einen Grund, warum DataGrid nicht nur ein RowsDeleted-Ereignis hat? WPF entfernt standardmäßig die Zeile, wenn Sie die Löschtaste drücken. Also macht es bereits diese Logik und führt eine Schleife über die gelöschten Zeilen. Warum können sie nicht einfach einen Event-Handler hinzufügen, so dass ich diesen Code nicht kopieren und die Schlüssel nicht überprüfen muss? – Chad

+16

Das ist nicht sehr nett, wenn Sie eine Zelle bearbeiten und den Löschschlüssel verwenden, um einige Zeichen in der Zelle zu entfernen, werden Sie am Ende die ganze Zeile löschen. – epalm

+2

@epalm Wenn du den 'foreach' Code innerhalb' if (grid.SelectedItems.Count> 0) 'wie Edward Tanguay hinzugefügt hast, dann sollte alles funktionieren. Aber danke, dass du es aufgezeigt hast! –

-1

Sie wollen die KeyUp oder KeyDown Ereignis behandeln und die gedrückte Taste für Löschen überprüfen.

private void OnKeyDown(object sender, KeyEventArgs e) { 
    if (Key.Delete == e.Key) { 
    // Delete pressed 
    } 
} 
+5

Das KeyDown-Ereignis wird nicht ausgelöst, wenn ich eine Taste gedrückt halte (ungerade), PreviewKeyDown funktioniert jedoch –

17

Was sind Sie verbindlich Ihr Datagrid? Im Idealfall sollten Sie auf CollectionChanged-Ereignisse in der Sammlung reagieren, an die Sie binden. Auf diese Weise wird Ihre Logik (Löschen von entfernten Elementen) von Ihrer Benutzeroberfläche getrennt.

Sie können eine Observable-Sammlung erstellen, die Ihre Objekte enthält, und sie nur zu diesem Zweck an ItemsSource binden, wenn die ursprüngliche Sammlung nicht über die erforderlichen Ereignisse verfügt.

Es passt vielleicht nicht zu Ihrem spezifischen Setup, aber so mache ich es normalerweise.

+0

Ich stimme völlig mit diesem Ansatz. Eine ObservableCollection ermöglicht Ihrem ViewModel, Änderungen an der zugrunde liegenden Datenquelle zu verarbeiten. Sie müssen sich nicht auf Code-Behind verlassen ... nichts ist grob falsch damit, es über Code-Behind zu erledigen ... einfach sauberer mit dem ViewModel. –

3

Bitte folgen Sie dem untenstehenden Code. Ich bin mit dem folgenden Code gelungen.

Bitte lassen Sie mich wissen, wenn Änderungen erforderlich sind.

private void grdEmployee_PreviewKeyDown(object sender, KeyEventArgs e) 
    { 

     if (e.Device.Target.GetType().Name == "DataGridCell") 
     { 
      if (e.Key == Key.Delete) 
      { 
       MessageBoxResult res = MessageBox.Show("Are you sure want to delete?", "Confirmation!", MessageBoxButton.YesNo,MessageBoxImage.Question); 
       e.Handled = (res == MessageBoxResult.No); 
      } 
     } 
    } 
7

XAML

<DataGrid ItemsSource="{Binding}" CommandManager.PreviewCanExecute="Grid_PreviewCanExecute" /> 

-Code hinter

private void Grid_PreviewCanExecute(object sender, CanExecuteRoutedEventArgs e) 
{ 
    DataGrid grid = (DataGrid)sender; 
    if (e.Command == DataGrid.DeleteCommand) 
    { 
    if (MessageBox.Show(String.Format("Would you like to delete {0}", (grid.SelectedItem as Person).FirstName), "Confirm Delete", MessageBoxButton.OKCancel) != MessageBoxResult.OK) 
     e.Handled = true; 
    } 
} 
0

ein wenig zu spät zur Party, aber Inferis Antwort anzuschalten:

Dim isEditing = False 
AddHandler dg.BeginningEdit, Sub() isEditing = True 
AddHandler dg.RowEditEnding, Sub() isEditing = False 
AddHandler dg.PreviewKeyDown, Sub(obj, ev) 
    If e.Key = Key.Delete AndAlso Not isEditing Then ... 

Dies behebt epalms Kommentar: "Wenn Sie eine Zelle bearbeiten und die lösche Schlüssel, um einige Zeichen in der Zelle zu entfernen, du wirst am Ende die ganze Reihe löschen "