2009-03-24 1 views
32

Desidero abilitare l'utente a evidenziare una riga su WPF DataGrid e premere il tasto di cancellazione per eliminare la riga.Che cos'è l'evento "premuto il tasto cancella" per il Datagrid WPF?

  • la funzionalità è già integrato nel UI della griglia, in modo per l'utente, la riga scompare
  • Attualmente gestire questo sull'evento SelectionChanged (codice qui sotto)
  • I ciclo attraverso tutti i "e.RemovedItems" ed eliminarli con LINQ

il problema è: anche quando semplicemente sE letta una riga e spostati da essa, viene attivato il cambio di selezione e quella riga è in e.RemovedItems (che è dispari, perché scegliere semplicemente qualcosa inserito in un contenitore RemovedItems?).

Quindi, sto cercando un evento DeleteKeyPressed così posso semplicemente gestirlo. Come si chiama quell'evento?

Sto utilizzando il toolkit di marzo 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; 
    } 
} 

RISPOSTA:

Grazie lnferis, che era esattamente quello che stavo cercando, qui è il mio evento di gestione dell'eliminazione finito per il datagrid, nota che l'evento KeyDown non si attiva per qualche motivo.

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

Il KeyDown non dovrebbe mai arrivare qui perché è già gestore (e.Handled = true) nel gestore precedente nella bolla. – Shimmy

risposta

25

Le voci RemovedItems riflette gli elementi rimossi dalla selezione, e non dalla rete.

gestire l'evento PreviewKeyDown, e utilizzare la proprietà SelectedItems per eliminare le righe selezionate c'è:

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

C'è un motivo per cui DataGrid non ha solo un evento RowsDeleted? WPF, per impostazione predefinita, rimuove graficamente la riga quando si preme il tasto Canc. Quindi, sta già facendo questa logica e fa il giro delle righe cancellate. Perché non possono semplicemente aggiungere un gestore di eventi in modo da non dover duplicare questo codice e controllare le chiavi. – Chad

+16

Non è molto bello, se stai modificando una cella e usi il tasto Canc per rimuovere alcuni caratteri nella cella, finirai per cancellare l'intera riga. – epalm

+2

@epalm se aggiungi il codice 'foreach' dentro' if (grid.SelectedItems.Count> 0) 'come ha fatto Edward Tanguay, allora tutto dovrebbe funzionare. Ma grazie per avermelo fatto notare! –

-1

Si desidera gestire l'evento KeyUp o KeyDown e verificare il tasto premuto per Delete.

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

l'evento KeyDown non si attiva quando si preme un tasto giù (dispari), PreviewKeyDown funziona anche se –

17

Cosa stai rilegare il DataGrid a? Idealmente, dovresti reagire agli eventi CollectionChanged sulla raccolta a cui sei vincolante. In questo modo, la tua logica (eliminazione degli elementi rimossi) sarà separata dalla tua interfaccia utente.

È possibile creare una raccolta Observable contenente gli oggetti e associarla a ItemsSource solo a tale scopo se la raccolta originale non presenta gli eventi necessari.

Potrebbe non essere adatto alla configurazione specifica, ma è così che solitamente lo faccio.

+0

Sono totalmente d'accordo con questo approccio. Una ObservableCollection consente a ViewModel di gestire qualsiasi modifica alla sorgente di dati del database sottostante. Non devi fare affidamento su code-behind ... niente di gravemente sbagliato nel farlo in modo automatico tramite code-behind ... semplicemente più pulito usando ViewModel. –

3

Si prega di seguire il codice sottostante. Sono riuscito con il codice qui sotto.

Per favore fatemi sapere se sono necessarie modifiche.

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" /> 

codice dietro

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

Un po 'tardi alla festa, ma per ottenere Inferis risposta di lavoro:

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 ... 

questo risolve epalms commento: "se stai modificando una cella e usi il cancella la chiave per rimuovere alcuni caratteri nella cella, finirai per cancellare l'intera riga "