{"id":129,"date":"2012-10-11T19:49:01","date_gmt":"2012-10-11T18:49:01","guid":{"rendered":"http:\/\/tech.fabienletort.com\/?p=129"},"modified":"2012-10-11T19:49:01","modified_gmt":"2012-10-11T18:49:01","slug":"ajouter-du-texte-dans-une-datagridviewcheckboxcell","status":"publish","type":"post","link":"https:\/\/tech.fabienletort.com\/?p=129","title":{"rendered":"Ajouter du texte dans une DataGridViewCheckBoxCell"},"content":{"rendered":"<p>Tout d&rsquo;abord expliquons pour j&rsquo;ai ce besoin. Pour un projet (pro) une colonne de mon DataGrid affiche en information textuelle, une valeur num\u00e9rique modifiable. Oui mais voil\u00e0 sous certaines conditions, certaines lignes de cette colonne ne peuvent avoir que 0 ou 1 comme valeur num\u00e9rique. En m&rsquo;abonnant \u00e0 l&rsquo;\u00e9v\u00e8nement <a title=\"MSDN - DataGridView.DataBindingComplete, \u00e9v\u00e9nement\" href=\"http:\/\/msdn.microsoft.com\/fr-fr\/library\/system.windows.forms.datagridview.databindingcomplete.aspx\" target=\"_blank\">DataBindingComplete<\/a>, j&rsquo;ai donc modifi\u00e9 \u00e0 la vol\u00e9e ces cellules en cellule avec une case \u00e0 cocher (<a title=\"MSDN - DataGridViewCheckBoxCell, classe\" href=\"http:\/\/msdn.microsoft.com\/fr-fr\/library\/system.windows.forms.datagridviewcheckboxcell%28v=vs.80%29.aspx\" target=\"_blank\">DataGridViewCheckBoxCell<\/a>). Bien entendu, je trouvais cela un peu moins parlant. Une ligne avec une valeur num\u00e9rique pouvait \u00eatre suivie d&rsquo;une case \u00e0 cocher dans la m\u00eame colonne. A la base, l&rsquo;id\u00e9e de la case \u00e0 cocher, c&rsquo;\u00e9tait surtout pour aider au changement de la valeur. Pourquoi donc \u00e9diter ce texte si on ne peut que mettre un 1 ou 0 ? Pour rendre plus claire cette colonne, j&rsquo;ai donc eu l&rsquo;id\u00e9e de faire appara\u00eetre ce 1 ou ce 0 \u00e0 c\u00f4t\u00e9 de la case \u00e0 cocher.<\/p>\n<p>Bien entendu cet objet n&rsquo;existe pas de base dans le framework. Comme je sais qu&rsquo;il ne faut pas r\u00e9inventer la roue, je suis parti sur le net \u00e0 la conqu\u00eate de la chose. Et j&rsquo;ai trouv\u00e9 quelque chose, mais qui ne correspondait pas exactement \u00e0 mes besoins&#8230; forc\u00e9ment ! Mais cette source d&rsquo;inspiration m&rsquo;a \u00e9t\u00e9 forte utile.<\/p>\n<h2>L&rsquo;inspiration<\/h2>\n<p><a title=\"Extending The DataGridViewCheckBoxCell To Include Text\" href=\"http:\/\/www.murrayhilltech.com\/articles\/articles.aspx?key=7\" target=\"_blank\">Extending The DataGridViewCheckBoxCell To Include Text<\/a><\/p>\n<p>Dans cet article l&rsquo;auteur veut faire la m\u00eame chose, mais pas pour le m\u00eame besoin. Au final, comme le montre sa capture finale,\u00a0 il semble vouloir avoir une liste de choix dans une ligne. Pour faire simple, le texte mis \u00e0 cot\u00e9 de la case \u00e0 cocher est un simple texte statique. Sa solution semble donc r\u00e9ellement utile que dans le cas d&rsquo;une liste de choix.<\/p>\n<p><a href=\"http:\/\/www.murrayhilltech.com\/articles\/articles.aspx?key=7\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" title=\"Extending The DataGridViewCheckBoxCell To Include Text\" src=\"http:\/\/www.murrayhilltech.com\/images\/multicolumnheader.png\" alt=\"\" width=\"600\" height=\"109\" \/><\/a><\/p>\n<p>Je vais tout de m\u00eame me baser sur sa solution du moins en point de d\u00e9part, car au final, j&rsquo;ai pas mal modifi\u00e9 (perfectionn\u00e9 ?) certains points.<br \/>\nDans la suite, mes commentaires seront donc beaucoup bas\u00e9 sur son exemple.<\/p>\n<h2>Ma solution<\/h2>\n<p>Tout comme Murray, je vais donc avoir besoin de d\u00e9finir 2 classes : <strong>DataGridViewCheckBoxTextColumn<\/strong> et <strong>DataGridViewCheckBoxTextCell<\/strong>. En effet, pour avoir une solution g\u00e9n\u00e9rique, la d\u00e9finition de la colonne correspondante est \u00e0 faire. Ces 2 classes \u00e9tendront donc respectivement les classes <em>DataGridViewCheckBoxColumn<\/em> et <em>DataGridViewCheckBoxCell<\/em>.<\/p>\n<h3>DataGridViewCheckBoxTextCell<\/h3>\n<p>Tout comme Muray, on peut commencer par d\u00e9finir cette classe. C&rsquo;est tr\u00e8s simple, on modifie juste le template de la cellule par d\u00e9faut et le tour est jou\u00e9.<\/p>\n<pre>using System;\r\nusing System.Windows.Forms;\r\n\r\nnamespace Kerlink.Windows.Forms\r\n{\r\n\u00a0\u00a0\u00a0 public class DataGridViewCheckBoxTextColumn : DataGridViewCheckBoxColumn\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public DataGridViewCheckBoxTextColumn()\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 this.CellTemplate = new DataGridViewCheckBoxTextCell();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 }\r\n}<\/pre>\n<h3>DataGridViewCheckTextCell<\/h3>\n<p>Voil\u00e0 le gros du travail. Contrairement \u00e0 Murray, je ne vais pas commencer par ajouter des propri\u00e9t\u00e9s \u00e0 cette classe. Tout comme lui, j&rsquo;ai envie de faire quelque chose de g\u00e9n\u00e9rique, j\u00a0\u00bbajouterais donc des propri\u00e9t\u00e9s au fur et \u00e0 mesure que si cela est r\u00e9ellement n\u00e9cessaire. Je vais tenter d&rsquo;utiliser au maximum ce qui est d\u00e9j\u00e0 d\u00e9finie dans mon objet de base, la classe <a title=\"MSDN - DataGridViewCheckBoxCell, classe\" href=\"http:\/\/msdn.microsoft.com\/fr-fr\/library\/system.windows.forms.datagridviewcheckboxcell%28v=vs.80%29.aspx\" target=\"_blank\">DataGridViewCheckBoxCell<\/a>. Bref, ici je n&rsquo;ajoute donc pas les propri\u00e9t\u00e9s Enabled, Text, Color et Font d\u00e9finie par Murray. Notre classe est donc d\u00e9j\u00e0 bien diff\u00e9rente dans sa d\u00e9finition de base :<\/p>\n<pre>public class DataGridViewCheckAndTextCell : DataGridViewCheckBoxCell\r\n{\r\n    public DataGridViewCheckAndTextCell()\r\n    {}\r\n}<\/pre>\n<p>Passons donc directement \u00e0 la deuxi\u00e8me action propos\u00e9e par Murray : surcharger la m\u00e9thode <a title=\"MSDN - DataGridViewCheckBoxCell.Paint, m\u00e9thode\" href=\"http:\/\/msdn.microsoft.com\/fr-fr\/library\/system.windows.forms.datagridviewcheckboxcell.paint%28v=vs.80%29.aspx\" target=\"_blank\">DataGridViewCheckBoxCell.Paint()<\/a>. Nous allons donc en premier lieu appel\u00e9 la m\u00e9thode m\u00e8re (qui fait ce qu&rsquo;elle aura \u00e0 faire, cela ne nous regarde pas) puis ajouter notre mixture locale. Voil\u00e0 la b\u00eate, qui est bien diff\u00e9rent de celle de Murray, plus courte et plus bas\u00e9e sur les propri\u00e9t\u00e9s existantes de la classe. De plus le placement du texte sera un peu plus propre (je trouve), c&rsquo;est \u00e0 dire correctement aligner (verticalement) avec les autres cellules de texte, contrairement au r\u00e9sultat de la solution de Murray. Sans plus tarder, le code :<\/p>\n<pre>protected override void Paint(System.Drawing.Graphics graphics, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)\r\n{\r\n    \/\/ Call the base method (which must draw the checkbox)\r\n    base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);\r\n\r\n    \/\/ Get the actual content Area (area where the checkbox must be)\r\n    System.Drawing.Rectangle contentBounds = this.GetContentBounds(rowIndex);\r\n\r\n    \/\/ Get Area Where String Must be Added (at 2px on the right of the checkbox)\r\n    System.Drawing.Rectangle stringArea = new System.Drawing.Rectangle();\r\n    stringArea.X = cellBounds.X + contentBounds.Right + 2;\r\n    stringArea.Y = cellBounds.Y + contentBounds.Top;\r\n    stringArea.Height = contentBounds.Height;\r\n    stringArea.Width = cellBounds.Width - contentBounds.Right - 2 - 2;\r\n\r\n    \/\/ Convert DataGridViewContentAlignment to StringFormat\r\n    System.Drawing.StringFormat format = cellStyle.Alignment.ToStringFormat();\r\n\r\n    \/\/ Draw the cell value inside the computed area\r\n    graphics.DrawString(this.Value.ToString(), cellStyle.Font, new System.Drawing.SolidBrush(cellStyle.ForeColor), stringArea, format);\r\n}<\/pre>\n<p>Ce qu&rsquo;on fait est donc tr\u00e8s simple. Contrairement \u00e0 Murray, pas besoin de redessiner la checkbox. On a pas de notion de checkbox Enabled: ici, ce n&rsquo;est pas une liste de choix. On va donc directement dessiner notre texte. On va donc passer tout sa partie de v\u00e9rification des propri\u00e9t\u00e9s et d&rsquo;initialisation de variable. On commence directement \u00e0 d\u00e9finir notre espace o\u00f9 le texte doit \u00eatre dessiner, et non pas un point de d\u00e9part comme Muray. La d\u00e9finition d&rsquo;une zone nous aidera pour l&rsquo;alignement du texte dans cette derni\u00e8re.<br \/>\nOn r\u00e9cup\u00e8re donc la zone occup\u00e9e par le contenu actuel : contentBounds via l&rsquo;appel \u00e0 <a title=\"DataGridViewCell.GetContentBounds, m\u00e9thode (Int32)\" href=\"http:\/\/msdn.microsoft.com\/fr-fr\/library\/ms158761%28v=vs.110%29.aspx\" target=\"_blank\">GetContentBounds<\/a>. On peut alors d\u00e9finir notre rectangle qui se situera \u00e0 2 pixel \u00e0 droite du contenu actuel, de m\u00eame hauteur que le contenu actuel, et de longueur maximum, c&rsquo;est \u00e0 dire ce qui reste de disponible dans la cellule en gardant une marge de 2 pixels sur sa droite.<\/p>\n<p>A ce stade, afin de dessiner le texte, il nous manque certains param\u00e8tre par rapport \u00e0 Murray : le texte, la police et sa couleur. Comme pr\u00e9cis\u00e9 plus haut, je vais utiliser les param\u00e8tres d\u00e9j\u00e0 d\u00e9finies dans la classe ! Il suffit de les trouver&#8230; Ainsi, pour le texte, on utilisera donc la valeur actuelle associ\u00e9 \u00e0 notre DataGridViewCheckBox. En effet dans mon cas, cette valeur est soit le chiffre 1 ou 0. Pour la police, rien ne sert d&rsquo;ajouter une propri\u00e9t\u00e9, le param\u00e8tre cellSyle (de type <a title=\"DataGridViewCellStyle, classe\" href=\"http:\/\/msdn.microsoft.com\/fr-fr\/library\/system.windows.forms.datagridviewcellstyle%28v=vs.100%29.aspx\" target=\"_blank\">DataGridViewCellStyle<\/a>) de la m\u00e9thode Paint contient d\u00e9j\u00e0 cette information. En effet, toute <a title=\"MSDN - DataGridViewCell, classe\" href=\"http:\/\/msdn.microsoft.com\/fr-fr\/library\/system.windows.forms.datagridviewcell%28v=vs.100%29.aspx\" target=\"_blank\">DataGridViewCell<\/a> a une telle propri\u00e9t\u00e9. De m\u00eame pour la couleur.<\/p>\n<p>Pour finir, par rapport \u00e0 Murray, on dessine notre texte dans une surface. Cela nous permet donc d&rsquo;aligner horizontalement et verticalement ce texte dans cette surface. La m\u00e9thode <a title=\"MSDN - Graphics.DrawString, m\u00e9thode \" href=\"http:\/\/msdn.microsoft.com\/fr-fr\/library\/system.drawing.graphics.drawstring.aspx\" target=\"_blank\">DrawString<\/a> utilise le type <a title=\"MSDN - StringFormat, classe\" href=\"http:\/\/msdn.microsoft.com\/fr-fr\/library\/system.drawing.stringformat.aspx\" target=\"_blank\">StringFormat<\/a> pour se faire. Une propri\u00e9t\u00e9 d&rsquo;alignement existe d\u00e9j\u00e0 dans notre style de cellule, mais elle est de type DataGridViewContentAlignement. Une petite m\u00e9thode d&rsquo;extension (ou une m\u00e9thode statique si vous \u00eates en .net2) et le tour est jou\u00e9.<\/p>\n<p>On est donc en mesure de dessiner notre texte via l&rsquo;appel \u00e0 DrawString de l&rsquo;objet graphics.<\/p>\n<p>Pour information, ci joint le code du convertisseur de type :<\/p>\n<pre>public static class DataGridViewContentAlignmentHelper\r\n{\r\n    public static System.Drawing.StringFormat ToStringFormat(this DataGridViewContentAlignment alignement)\r\n    {\r\n        System.Drawing.StringFormat format = new System.Drawing.StringFormat();\r\n\r\n        \/\/ Set the Vertical Alignement (could transform enum in string and test value ?)\r\n        switch (alignement)\r\n        {\r\n            case DataGridViewContentAlignment.BottomCenter:\r\n            case DataGridViewContentAlignment.BottomLeft:\r\n            case DataGridViewContentAlignment.BottomRight:\r\n                format.LineAlignment = System.Drawing.StringAlignment.Far;\r\n                break;\r\n\r\n            case DataGridViewContentAlignment.MiddleCenter:\r\n            case DataGridViewContentAlignment.MiddleLeft:\r\n            case DataGridViewContentAlignment.MiddleRight:\r\n            case DataGridViewContentAlignment.NotSet:\r\n                format.LineAlignment = System.Drawing.StringAlignment.Center;\r\n                break;\r\n\r\n            case DataGridViewContentAlignment.TopCenter:\r\n            case DataGridViewContentAlignment.TopLeft:\r\n            case DataGridViewContentAlignment.TopRight:\r\n                format.LineAlignment = System.Drawing.StringAlignment.Near;\r\n                break;\r\n        }\r\n\r\n        \/\/ Set the Horizontal Alignement (could transform enum in string and test value ?)\r\n        switch (alignement)\r\n        {\r\n            case DataGridViewContentAlignment.BottomCenter:\r\n            case DataGridViewContentAlignment.MiddleCenter:\r\n            case DataGridViewContentAlignment.TopCenter:\r\n                format.Alignment = System.Drawing.StringAlignment.Center;\r\n                break;\r\n\r\n            case DataGridViewContentAlignment.BottomLeft:\r\n            case DataGridViewContentAlignment.MiddleLeft:\r\n            case DataGridViewContentAlignment.TopLeft:\r\n                format.Alignment = System.Drawing.StringAlignment.Near;\r\n                break;\r\n\r\n            case DataGridViewContentAlignment.BottomRight:\r\n            case DataGridViewContentAlignment.MiddleRight:\r\n            case DataGridViewContentAlignment.NotSet:\r\n            case DataGridViewContentAlignment.TopRight:\r\n                format.Alignment = System.Drawing.StringAlignment.Far;\r\n                break;\r\n        }\r\n\r\n        return format;\r\n    }\r\n}<\/pre>\n<h3>1er essai<\/h3>\n<p>Contrairement \u00e0 Murray on a pas fini. Certes la colonne est disponible depuis le designer. Certes on voit la magie apparaitre. Mais comme on pouvait s&rsquo;y attendre, il manque tout le c\u00f4t\u00e9 dynamique. On a beau cocher ou d\u00e9cocher, pas de changement du texte associ\u00e9.<\/p>\n<p>La premi\u00e8re question \u00e0 se poser, c&rsquo;est comment fait donc une <em>DataGridViewCheckBoxCell<\/em> pour changer sa valeur quand celle-ci n&rsquo;est pas un simple boolean ?<\/p>\n<p>On cherche, et la r\u00e9ponse est \u00e0 port\u00e9 de main ou plut\u00f4t \u00e0 port\u00e9e de 2 propri\u00e9t\u00e9s :<\/p>\n<ul>\n<li><a title=\"MSDN - DataGridViewCheckBoxCell.TrueValue, propri\u00e9t\u00e9 \" href=\"http:\/\/msdn.microsoft.com\/fr-fr\/library\/system.windows.forms.datagridviewcheckboxcell.truevalue%28v=vs.100%29.aspx\" target=\"_blank\">TrueValue<\/a> : Obtient ou d\u00e9finit la valeur sous-jacente correspondant \u00e0 une valeur de cellule <strong>true<\/strong>.<\/li>\n<li><a title=\"MSDN - DataGridViewCheckBoxCell.FalseValue, propri\u00e9t\u00e9\" href=\"http:\/\/msdn.microsoft.com\/fr-fr\/library\/system.windows.forms.datagridviewcheckboxcell.falsevalue%28v=vs.100%29.aspx\" target=\"_blank\">FalseValue<\/a> :\u00a0 Obtient ou d\u00e9finit la valeur sous-jacente correspondant \u00e0 une valeur de cellule <strong>false<\/strong>.<\/li>\n<\/ul>\n<p>Du m\u00eame acabits, on a aussi la <a title=\"MSDN - DataGridViewCheckBoxCell.IndeterminateValue, propri\u00e9t\u00e9\" href=\"http:\/\/msdn.microsoft.com\/fr-fr\/library\/system.windows.forms.datagridviewcheckboxcell.indeterminatevalue%28v=vs.100%29.aspx\" target=\"_blank\">IndeterminateValue<\/a>.<\/p>\n<p>Une fois la databinding en place, on peut donc aussi pr\u00e9ciser comment notre checkbox met \u00e0 jour sa donn\u00e9e. Ce code est donc du c\u00f4t\u00e9 du client de notre classe. Dans mon cas, je devrais pr\u00e9ciser une TrueValue \u00e0 1 et une FalseValue \u00e0 0. A noter que ce client peut le d\u00e9finir via les m\u00eame propri\u00e9t\u00e9s disponible au niveau de la <em>DataGridViewCheckBoxColumn<\/em>.<\/p>\n<h3>2\u00e8me essai<\/h3>\n<p>La mise \u00e0 jour a lieu certes. Mais celle ci n\u2019op\u00e8re que quand on sort du mode \u00e9dition de la cellule (en cliquant sur une autre). On abouti l\u00e0 sur une grosse limite des CheckBox cell qui semble connue. En effet le chemin habituel google -&gt; stackoverflow m&rsquo;a fait aboutir sur <a title=\"StackOverflow - DataGridView with CheckBox cell problem\" href=\"http:\/\/stackoverflow.com\/questions\/4000708\/datagridview-with-checkbox-cell-problem\" target=\"_blank\">cette solution<\/a>.<\/p>\n<h3>Contexte Dynamique<\/h3>\n<p>Il faut donc s&rsquo;abonner \u00e0 l\u2019\u00e9v\u00e9nement <a title=\"MSDN - datagridview.currentcelldirtystatechanged event\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.windows.forms.datagridview.currentcelldirtystatechanged.aspx\" rel=\"nofollow\" target=\"_blank\">CurrentCellDirtyStateChanged<\/a> du DataGridView pour forcer la validation du changement en cours.<\/p>\n<p>Oui, mais voil\u00e0 la propri\u00e9t\u00e9 interne <a title=\"MSDN - DataGridViewCheckBoxCell.DataGridView, propri\u00e9t\u00e9\" href=\"http:\/\/msdn.microsoft.com\/fr-fr\/library\/system.windows.forms.datagridviewelement.datagridview%28v=vs.80%29.aspx\" target=\"_blank\">DataGridView<\/a>\u00a0 n&rsquo;est pas disponible lors de la construction de notre classe. Pour r\u00e9cup\u00e9rer son instance, on va donc surcharger la m\u00e9thode prot\u00e9g\u00e9e <a title=\"MSDN - DataGridViewCell.OnDataGridViewChanged, m\u00e9thode\" href=\"http:\/\/msdn.microsoft.com\/fr-fr\/library\/system.windows.forms.datagridviewcell.ondatagridviewchanged%28v=vs.80%29.aspx\" target=\"_blank\">OnDataGridViewChanged<\/a>.<\/p>\n<p>Passons donc au code :<\/p>\n<pre>private DataGridView _previousDataGridView = null;\r\n\/\/ get datagridview instance to can subribe to CurrentCellDirtyStateChanged event.\r\nprotected override void OnDataGridViewChanged()\r\n{\r\n    base.OnDataGridViewChanged();\r\n\r\n    if (this.DataGridView != _previousDataGridView)\r\n\u00a0   {\r\n        if (_previousDataGridView != null)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0    \/\/ unsubscribe from previous DataGridView\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 _previousDataGridView.CurrentCellDirtyStateChanged -= DataGridView_CurrentCellDirtyStateChanged;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (this.DataGridView != null)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ subscribe to new related DataGridView\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 this.DataGridView.CurrentCellDirtyStateChanged += new EventHandler(DataGridView_CurrentCellDirtyStateChanged);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 }\r\n}\r\n\r\n\/\/ Force the databound property update (for this checkbox) as soon as the check box is checked\/unchecked (default is after the CellLeave event)\r\nvoid DataGridView_CurrentCellDirtyStateChanged(object sender, EventArgs e)\r\n{\r\n\u00a0\u00a0\u00a0 \/\/ we can't use this.DataGridView : it can be null in this context !\r\n\u00a0\u00a0\u00a0 DataGridView dgv = sender as DataGridView;\r\n\r\n\u00a0\u00a0\u00a0 \/\/ Always directly commit the uncommited changes of the current cell.\r\n\u00a0\u00a0\u00a0 if ((dgv.CurrentCell == this) &amp;&amp; (dgv.IsCurrentCellDirty))\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 dgv.CommitEdit(DataGridViewDataErrorContexts.Commit);\r\n\u00a0\u00a0\u00a0 }\r\n}<\/pre>\n<p>Voil\u00e0 pas grand chose \u00e0 ajouter pour expliquer. Au niveau de <a title=\"MSDN - DataGridViewElement.OnDataGridViewChanged, m\u00e9thode \" href=\"http:\/\/msdn.microsoft.com\/fr-fr\/library\/system.windows.forms.datagridviewelement.ondatagridviewchanged%28v=vs.100%29.aspx\" target=\"_blank\">OnDataGridViewChanged<\/a>, j&rsquo;ai fait \u00e7a propre : je me d\u00e9sinscris de l&rsquo;ancien pour m&rsquo;inscrire sur le nouveau. Je sais pas si un changement est possible, mais en tout cas, cette m\u00e9thode peut \u00eatre appel\u00e9 alors que this.DataGridView est nul en d\u00e9but d&rsquo;ex\u00e9cution. Bref, j&rsquo;ai pr\u00e9f\u00e9rais assurer le coup.<\/p>\n<p>Enfin dans le traitement de l&rsquo;\u00e9v\u00e8nement <a title=\"MSDN - DataGridView.CurrentCellDirtyStateChanged, \u00e9v\u00e9nement\" href=\"http:\/\/msdn.microsoft.com\/fr-fr\/library\/system.windows.forms.datagridview.currentcelldirtystatechanged.aspx\" target=\"_blank\">CurrentCellDirtyStateChanged<\/a>, on applique la solution trouv\u00e9e. Seul remarque, on ne peut pas utiliser this.DataGridView ici. Bref, soit on r\u00e9cup\u00e9re la DataGridView via le sender (ce que j&rsquo;ai fait), ou on pourrait aussi utiliser notre variable locale _previousDataGridView.<\/p>\n<h3>3\u00e8me essai<\/h3>\n<p>C&rsquo;est parfait. On clique, la valeur change directement. Good job.<\/p>\n<h3>Au final<\/h3>\n<p>Ces petites recherches ont \u00e9t\u00e9 int\u00e9ressantes. Comme d&rsquo;habitude on prend des bouts de solution \u00e0 droite \u00e0 gauche pour faire ce qu&rsquo;on veut. On pourrait imaginer une classe un peu plus g\u00e9n\u00e9rique s&rsquo;adaptant aussi bien au besoin de Murray ou au miens (changement de comportement via une Propri\u00e9t\u00e9 ?). Enfin, en r\u00e9fl\u00e9chissant \u00e0 \u00e7a, je me demande aussi si cela reste toujours une bonne id\u00e9e de partir de <em>DataGridViewCheckBoxCell. <\/em>En h\u00e9ritant de <em>DataGridViewCell,<\/em> on aura pas mal de chose \u00e0 refaire (tout ce qui d\u00e9finie la checkbox) mais au moins on serait pas oblig\u00e9 d&rsquo;utiliser des astuces pour r\u00e9ussir \u00e0 se rendre compte du changement d&rsquo;\u00e9tat de la CheckBox. En la g\u00e9rant totallement on pourrait dire en revoir \u00e0 l&rsquo;\u00e9v\u00e8nement CurrentCellDirtyChanged. Un \u00e9v\u00e8nement li\u00e9 \u00e0 notre CheckBox serait directement utilis\u00e9&#8230; Voil\u00e0 une autre solution envisageable.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Tout d&rsquo;abord expliquons pour j&rsquo;ai ce besoin. Pour un projet (pro) une colonne de mon DataGrid affiche en information textuelle, une valeur num\u00e9rique modifiable. Oui mais voil\u00e0 sous certaines conditions, certaines lignes de cette colonne ne peuvent avoir que 0 ou 1 comme valeur num\u00e9rique. En m&rsquo;abonnant \u00e0 l&rsquo;\u00e9v\u00e8nement DataBindingComplete, j&rsquo;ai donc modifi\u00e9 \u00e0 la [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10],"tags":[16,12,11,14,13,15],"class_list":["post-129","post","type-post","status-publish","format-standard","hentry","category-net","tag-net","tag-checkbox","tag-datagridview","tag-ihm","tag-texte","tag-winforms"],"_links":{"self":[{"href":"https:\/\/tech.fabienletort.com\/index.php?rest_route=\/wp\/v2\/posts\/129","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tech.fabienletort.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tech.fabienletort.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tech.fabienletort.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tech.fabienletort.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=129"}],"version-history":[{"count":12,"href":"https:\/\/tech.fabienletort.com\/index.php?rest_route=\/wp\/v2\/posts\/129\/revisions"}],"predecessor-version":[{"id":142,"href":"https:\/\/tech.fabienletort.com\/index.php?rest_route=\/wp\/v2\/posts\/129\/revisions\/142"}],"wp:attachment":[{"href":"https:\/\/tech.fabienletort.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=129"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tech.fabienletort.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=129"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tech.fabienletort.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=129"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}