Vérification boolé unique dans DataGridView, mise à jour de la database

J'ai un DataGridView avec une colonne de bit qui montre comme une checkbox. La colonne est "IsDefault" par son nom, ce qui implique que si cette cellule est cochée, toutes les autres cellules de cette colonne dans le DataTable doivent être décochées (seulement 1 cellule dans cette colonne est autorisée par défaut).

J'ai réussi à get ce comportement en gérant la modification de l'événement CellContentClick de DataGridView, c'est-à-dire:

private void ViewIconsDataGrid_CellContentClick(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex == -1 || e.ColumnIndex == -1) return; DataTable table = ViewIconsDataGrid.DataSource as DataTable; DataGridViewCell cell = ViewIconsDataGrid.Rows[e.RowIndex].Cells[e.ColumnIndex]; Guid rowID = (Guid)ViewIconsDataGrid.Rows[e.RowIndex].Cells["ID"].Value; if (cell.GetType() == typeof(DataGridViewCheckBoxCell)) { DataGridViewCheckBoxCell checkBoxCell = cell as DataGridViewCheckBoxCell; bool value = (bool)checkBoxCell.EditedFormattedValue, previous = (bool)checkBoxCell.Value; if (value != previous) { if (value == true) { Guid currentDefault; if(MyIcons.Defaults.TryGetValue(MyGroupID, out currentDefault)) { DataRow [] rows = table.Select("ID = '" + currentDefault.ToSsortingng() + "'"); if(rows.Length == 1) { rows[0]["IsDefault"] = false; } } } ViewIconsDataGrid.EndEdit(); table.AcceptChanges(); } } } 

Maintenant, clairement, j'essaie d'apporter des modifications à deux loggings dans le même DataTable ici. Le premier j'espère que le DataGridView change (quand l'user change l'état de la checkbox) et puis je fais une autre modification sur le DataTable pour décocher quelle ligne a déjà eu la vérification, espérant que propagera jusqu'à DataGridView. Je dois bien sûr valider les deux changements dans la database.

Voici le code de mise à jour de ma database, qui est un peu générique, c'est-à-dire que je passe une requête select pour la table entière et une table de données pour la mettre à jour:

 using (SqlConnection connection = new SqlConnection(ConfigurationManager.AppSettings["Connection"])) { connection.Open(); using (SqlDataAdapter adapter = new SqlDataAdapter(MyQuery, connection)) { adapter.InsertCommand = new SqlCommandBuilder(adapter).GetInsertCommand(); adapter.DeleteCommand = new SqlCommandBuilder(adapter).GetDeleteCommand(); adapter.UpdateCommand = new SqlCommandBuilder(adapter).GetUpdateCommand(); adapter.Update(MyTable); } } 

Le problème est donc que j'obtiens une exception lorsque j'essaie de mettre à jour la table après avoir apporté ces modifications: "Violation de la concurrency: UpdateCommand affecté 0 des loggings 1 attendus.". S'il n'y a pas de défaut par défaut, un seul logging est mis à jour et tout va bien.

Quelqu'un peut-il repérer mon erreur, ou voir un moyen plus facile pour moi de faire cela?

Édition 1: Dans le fragment ci-dessus, MyQuery ressemble à ceci:

 @"SELECT * From Picture WHERE ID_Group = '{0}' AND Deleted = 0 ORDER BY Created DESC 

{0} est le guid du groupe d'images que je suis en train de mettre à jour, c'est-à-dire qu'une requête select donne tous les loggings de la table Pictures qui sont membres de ce groupe.

L'appel à AcceptChanges modifie le RowState de chaque ligne de la table à Inchangé.
L'appel suivant à DataAdatper.Update (table) ne trouve rien à mettre à jour / insert ou supprimer.

Vous devez appeler la mise à jour sur l'input de l'user (comme un clic sur un button Enregistrer)

EDIT Pour compléter cette réponse avec les résultats ci-dessous de @Robinson

Vous pouvez RowChanged événement RowChanged pour la table qui gère l'événement CurrentCellDirtyStateChanged et valider manuellement l'édition sur DataGridView. Sinon, l'événement RowChanged est déclenché lorsque la ligne a perdu le focus.

Il y a deux problèmes ici:

Tout d'abord, les events DataGridView n'envoient pas correctement les modifications en cache, vous devez utiliser un autre événement, comme un clic de button , pour forcer DataGridView à mettre en cache les modifications.

L'autre problème "violation de la concurrency" est causé par l'insertion d'une nouvelle ligne dans une table avec une colonne Identity (généralement la key primaire). Je suggère d' utiliser un autre button pour les insertions et de forcer la nouvelle valeur d'identité dans DataGridView.

Lorsque vous mettez à jour, je suggère de faire des suppressions d'abord, et ensuite faire les mises à jour:

 // First process deletes. da.Update(dt.Select(null, null, DataViewRowState.Deleted)); // Next process updates. da.Update(dt.Select(null, null, DataViewRowState.ModifiedCurrent));