2011-06-04 4 views
1

J'utilise une technique similaire à http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/df77a277-91d4-41f1-a42a-0fa02a443ff4/ J'ai un DaataGridTemplateColumn construit, dans le code, et je tente de répondre à la « sélection de la ligne, cliquez ensuite sur » problème de case à cocher avec des grilles de données dans WPF .Utilisation de case à cocher dans DataGridTemplateColumn Questions WPF

Au sens général, cela fonctionne, mais si je veux déclencher un événement lorsque la case est cliqué (Ie CellEditEnding ou RowEditEnding), il semble que je ne peux pas (selon http://social.msdn.microsoft.com/Forums/en/wpf/thread/bf080945-0092-43f5-b0eb-42b2edf53dc7)

Il doit y avoir un façon de résoudre cela. J'ai pensé à utiliser un type d'événement routé sur ma colonne de modèle pour tenter de déclencher un événement de grille de données lorsque la case est cochée, mais cela pourrait devenir moche. En fin de compte, je dois être en mesure d'avoir une case à cocher 1 clic, et être en mesure de déclencher des événements de grille de données.

Aidez s'il vous plaît!

Edit: Si je peux obtenir RowEditEnding au feu (en quelque sorte:. Via le bullage ou autre) alors ce ne serait pas un problème ... Je ne peux tout simplement pas l'obtenir au feu ..

Tout le monde ?? ?

Merci

Répondre

0

La réponse ici est de ne pas traiter l'une des cases (ou tenter de) en RowEditEnding. Au lieu de cela, utilisez l'événement PropertyChange en écoutant la case à cocher à laquelle vous êtes lié, et agissez en conséquence (par exemple, sauvegardez les modifications lorsque la case est cochée)

1

Je suis tombé sur votre question et couriez dans la même direction. Voici ma situation et la solution et je pense que cela devrait fonctionner pour vous (et d'autres) aussi bien. J'ai une grille de données qui permet l'entrée de nouveaux éléments, donc les valeurs possibles vont de 0 à l'infini. Les utilisateurs devraient être en mesure de cliquer sur la case à cocher et de le cocher ou de décocher avec un seul clic. En outre, il existe d'autres champs qui peuvent également être mis à jour. Je devais créer un contrôle DataGrid personnalisé pour se concentrer automatiquement et commencer le montage de la case à cocher:

public class CheckboxDataGrid : DataGrid { 
     public CheckboxDataGrid() { 
      EventManager.RegisterClassHandler(typeof(DataGridCell), 
       DataGridCell.PreviewMouseLeftButtonDownEvent, 
       new RoutedEventHandler(this.OnPreviewMouseLeftButtonDown)); 
     } 


     private void OnPreviewMouseLeftButtonDown(object sender, RoutedEventArgs e) { 
      DataGridCell cell = sender as DataGridCell; 
      if (cell != null && !cell.IsEditing && !cell.IsReadOnly) { 

       var parentRow = cell.Parent as DataGridRow; 
       if (parentRow != null) { 
        SelectedIndex = parentRow.GetIndex(); 
       } 
       CurrentCell = new DataGridCellInfo(cell); 

       DependencyObject obj = FindVisualChild<CheckBox>(cell); 
       if (obj != null) { 
        BeginEdit(e); 
        System.Windows.Controls.CheckBox cb = (System.Windows.Controls.CheckBox)obj; 
        cb.Focus(); 
       } 
      } 
     } 
     public static TChild FindVisualChild<TChild>(DependencyObject obj) where TChild : DependencyObject { 
      for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) { 
       DependencyObject child = VisualTreeHelper.GetChild(obj, i); 
       if (child != null && child is TChild) { 
        return (TChild)child; 
       } else { 
        TChild childOfChild = FindVisualChild<TChild>(child); 
        if (childOfChild != null) 
         return childOfChild; 
       } 
      } 
      return null; 
     } 
    } 

J'ai aussi besoin d'un convertisseur d'ignorer le nouveau message de liaison point à cause de la façon qui gère WPF nouveaux éléments dans une grille de données:

public class IgnoreNewItemPlaceHolderConverter : IValueConverter { 
     private const string NewItemPlaceholderName = "{NewItemPlaceholder}"; 

     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { 
      return value; 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { 
      if (value != null && value.ToString() == NewItemPlaceholderName) 
       return DependencyProperty.UnsetValue; 
      return value; 
     } 

    } 

Voici le XAML relavent pour le DataGrid:

<chkDatagrid:CheckboxDataGrid AutoGenerateColumns="False" 
         ItemsSource="{Binding ElementName=dgPurchaseOrders, Path=SelectedItem.Releases, NotifyOnSourceUpdated=True}" AlternatingRowBackground="#1E000000" 
         DockPanel.Dock="Bottom" HorizontalAlignment="Left" SelectedItem="{Binding SelectedRelease, Mode=TwoWay, Converter={StaticResource ignoreNewItemPlaceHolderConverter}}" 
         MinHeight="100"> 
<b:Interaction.Triggers> 
          <b:EventTrigger EventName="RowEditEnding"> 
           <b:InvokeCommandAction Command="{Binding ReleaseRowEditEndingCommand}" CommandParameter="{Binding SelectedRelease}"/> 
          </b:EventTrigger> 
         </b:Interaction.Triggers> 
         <DataGrid.Columns> 
          <DataGridCheckBoxColumn Header="Is Paid" Binding="{Binding IsPaid, UpdateSourceTrigger=PropertyChanged}" /> 

          <DataGridTextColumn Header="Amount" Binding="{Binding Amount, UpdateSourceTrigger=PropertyChanged}" /> 
          <DataGridTextColumn Header="Description" Binding="{Binding Description, UpdateSourceTrigger=PropertyChanged}" /> 
          <DataGridTextColumn Header="Invoice Number" Binding="{Binding InvoiceNumber, UpdateSourceTrigger=PropertyChanged}" /> 
          <DataGridTextColumn Header="Invoice Receive Date" Binding="{Binding InvoiceRecvDate, UpdateSourceTrigger=PropertyChanged}" /> 
         </DataGrid.Columns> 
        </chkDatagrid:CheckboxDataGrid> 

Vous remarquerez quelques petites choses ici. Je suis abonné à l'événement RowEditEnding pour l'édition et la validation des colonnes et l'application du convertisseur à la nouvelle ligne.

Enfin, voici le code qui met à jour l'entité ci-joint:

private void OnReleaseRowEditEnding(object arg) { 
      if (arg != null) { 
       EMService.EMEntities etx = GetEMEntities(); 
       EMService.Release release = (EMService.Release)arg; 
       if (release.ReleaseID == 0) { 
        release.EncumbranceID = SelectedPurchaseOrder.EncumbranceID; 
        release.CreatedOn = DateTime.Now; 
        release.CreatedBy = CurrentUser.Username; 
        release.ModifiedOn = DateTime.Now; 
        release.ModifiedBy = CurrentUser.Username; 
        etx.AddObject("Releases", release); 
       } else { 
        EMService.Release existingRelease = etx.Releases.Where(e => e.ReleaseID == release.ReleaseID).First(); 
        existingRelease.Amount = release.Amount; 
        existingRelease.Description = release.Description; 
        existingRelease.InvoiceNumber = release.InvoiceNumber; 
        existingRelease.InvoiceRecvDate = release.InvoiceRecvDate; 
        existingRelease.IsPaid = release.IsPaid; 
        release.ModifiedOn = DateTime.Now; 
        release.ModifiedBy = CurrentUser.Username; 
        etx.UpdateObject(existingRelease); 
       } 
       etx.SaveChanges(); 
      } 
     } 

Il est beaucoup à digérer, mais il a fini par travailler à long terme. Qui savait que le DataGrid de WPF serait si putain.

Questions connexes