Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

User control custom et DataGridView [Débutant]


Sujet :

C#

  1. #1
    Membre du Club
    Homme Profil pro
    Inscrit en
    octobre 2013
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : octobre 2013
    Messages : 143
    Points : 43
    Points
    43
    Par défaut User control custom et DataGridView
    Bonjour

    Je développe une application dans laquelle j'ai un DataGridView qui est remplis automatiquement à partir d'un DataSet.
    Dans ce DataGridView j'ai une colonne "Commentaire" dans laquelle je souhaiterai y mettre un User Control custom. En gros, dans chacune des cellules de la colonne j'aimerai y mettre ce control.

    Le User Control que je souhaite faire est un simple label suivi d'un bouton (tout deux dans un TableLayoutPanel pour la disposition).

    J'ai suivi ce tuto d'exemple pour mettre en place mon ColumnType par rapport à mon User Control. Ainsi que ce post.

    Cependant, lorsque j'applique mon ColumnType à ma colonne "Commentaire" via la fenêtre d'édition de la form et que je lance l'application, la cellule est noire.

    J'ai pu comprendre qu'il fallait surcharger la fonction Paint pour dessiner correctement le control mais je produit des résultat pas très concluant ^^'

    Merci d'avance pour vos retours

    Voici le code de mon control :

    LabelButton.cs :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
     
    using System;
    using System.Windows.Forms;
     
    namespace ControlLibrary
    {
        public class LabelButtonColumn : DataGridViewColumn
        {
            public LabelButtonColumn()
                : base(new LabelButtonCell())
            {
            }
     
            public override DataGridViewCell CellTemplate
            {
                get { return base.CellTemplate; }
                set
                {
                    if (value != null && !value.GetType()
                        .IsAssignableFrom(typeof(LabelButtonCell)))
                        throw new InvalidCastException("It should be a custom Cell");
                    base.CellTemplate = value;
                }
            }
        }
     
        public class LabelButtonCell : DataGridViewCell
        {
            public LabelButtonCell()
                : base()
            {
            }
     
            public override Type ValueType
            {
                get
                {
                    return typeof(LabelButton);  
                }
            }
     
            public override Type FormattedValueType
            {
                get
                {
                    return typeof(string);
                }
            }
     
            //protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
            //{
            //    var ctrl = (LabelButton)value;
            //    var img = new Bitmap(cellBounds.Width, cellBounds.Height);
            //    ctrl.DrawToBitmap(img, new Rectangle(0, 0, ctrl.Width, ctrl.Height));
            //    graphics.DrawImage(img, cellBounds.Location);
            //}
        }
     
        public partial class LabelButton : UserControl
        {
            public LabelButton()
            {
                InitializeComponent();
            }
        }
    }
    LabelButton.Designer.cs :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
     
    namespace ControlLibrary
    {
        partial class LabelButton
        {
            /// <summary> 
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.IContainer components = null;
     
            /// <summary> 
            /// Clean up any resources being used.
            /// </summary>
            /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }
     
            #region Component Designer generated code
     
            /// <summary> 
            /// Required method for Designer support - do not modify 
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LabelButton));
                this.control_tlp = new System.Windows.Forms.TableLayoutPanel();
                this.control_btn = new System.Windows.Forms.Button();
                this.control_lb = new System.Windows.Forms.Label();
                this.control_tlp.SuspendLayout();
                this.SuspendLayout();
                // 
                // control_tlp
                // 
                this.control_tlp.ColumnCount = 2;
                this.control_tlp.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 75.22124F));
                this.control_tlp.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 24.77876F));
                this.control_tlp.Controls.Add(this.control_btn, 1, 0);
                this.control_tlp.Controls.Add(this.control_lb, 0, 0);
                this.control_tlp.Dock = System.Windows.Forms.DockStyle.Fill;
                this.control_tlp.Location = new System.Drawing.Point(0, 0);
                this.control_tlp.Name = "control_tlp";
                this.control_tlp.RowCount = 1;
                this.control_tlp.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
                this.control_tlp.Size = new System.Drawing.Size(113, 24);
                this.control_tlp.TabIndex = 0;
                // 
                // control_btn
                // 
                this.control_btn.Dock = System.Windows.Forms.DockStyle.Fill;
                this.control_btn.Image = ((System.Drawing.Image)(resources.GetObject("control_btn.Image")));
                this.control_btn.Location = new System.Drawing.Point(84, 0);
                this.control_btn.Margin = new System.Windows.Forms.Padding(0);
                this.control_btn.Name = "control_btn";
                this.control_btn.Size = new System.Drawing.Size(29, 24);
                this.control_btn.TabIndex = 0;
                this.control_btn.UseVisualStyleBackColor = true;
                // 
                // control_lb
                // 
                this.control_lb.AutoSize = true;
                this.control_lb.Dock = System.Windows.Forms.DockStyle.Fill;
                this.control_lb.Location = new System.Drawing.Point(3, 0);
                this.control_lb.Name = "control_lb";
                this.control_lb.Size = new System.Drawing.Size(78, 24);
                this.control_lb.TabIndex = 1;
                this.control_lb.Text = ". . .";
                this.control_lb.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
                // 
                // labelButton
                // 
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.Controls.Add(this.control_tlp);
                this.Name = "labelButton";
                this.Size = new System.Drawing.Size(113, 24);
                this.control_tlp.ResumeLayout(false);
                this.control_tlp.PerformLayout();
                this.ResumeLayout(false);
     
            }
     
            #endregion
     
            private System.Windows.Forms.TableLayoutPanel control_tlp;
            public System.Windows.Forms.Label control_lb;
            public System.Windows.Forms.Button control_btn;
        }
    }
      0  0

  2. #2
    Membre expert
    Inscrit en
    avril 2008
    Messages
    2 244
    Détails du profil
    Informations personnelles :
    Âge : 59

    Informations forums :
    Inscription : avril 2008
    Messages : 2 244
    Points : 3 769
    Points
    3 769
    Par défaut
    Bonjour

    Ton implementation est incomplete ,il manque le control d'edition:
    -derivé de ton UserControl et qui implemnte l'interface editing IDataGridViewEditingControl.

    ton code revu qui affiche ton usercontrol et son Labell adossé à un bouton , plus un bonus :
    Le bonus est une boite de dialogue d'ouverture d'un fichier texte contenant le commentaire lorsque on clique sur ton bouton ...
    Mais sur clic du du dit bouton on peut aussi bien faire surgir une boite de dialogue muni de boutons Ok et Cancel et un TextBox "crachoir" pour saisir un commentaire ...
    ton code de usercontrol revu :
    1/LabelButtonColumn
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    namespace ControlLib
    {
        public class LabelButtonColumn : DataGridViewColumn
        {
            public LabelButtonColumn()
                : base(new LabelButtonCell())
            {
            }
     
            public override DataGridViewCell CellTemplate
            {
                get
                {
                    return base.CellTemplate;
                }
                set
                {
                    // Ensure that the cell used for the template is a CalendarCell.
                    if (value != null &&
                        !value.GetType().IsAssignableFrom(typeof(LabelButtonCell)))
                    {
                        throw new InvalidCastException("Must be a CalendarCell");
                    }
                    base.CellTemplate = value;
                }
            }
        }
    }
    2/ LabelButtonCell
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
     
    namespace ControlLib
    {
        public class LabelButtonCell : DataGridViewTextBoxCell
        {
            private string defVal  ="..."; //valeur par defaut affichée lorsque on entre en mode edition (double clic sur cellule du dgv)
            public LabelButtonCell()
                : base()
            { }
     
            public override void InitializeEditingControl(int rowIndex, object
                initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
            {
                // Set the value of the editing control to the current cell value.
                base.InitializeEditingControl(rowIndex, initialFormattedValue,
                    dataGridViewCellStyle);
                LabelButton ctl =
                    DataGridView.EditingControl as LabelButton;
                // Use the default row value when Value property is null.
                if (this.Value == null)
                {
                    ctl.control_lb.Text = (string )this.DefaultNewRowValue;
                }
                else
                {
                    ctl.control_lb.Text = (string)this.Value;
                }
            }
     
            public override Type EditType
            {
                get
                {
                    // Return the type of the editing control that CalendarCell uses.
                    return typeof(  MyContainerControl);
                }
            }
     
            public override Type ValueType
            {
                get
                {
                    // Return the type of the value that CalendarCell contains.
     
                    return typeof(string );
                }
            }
     
            public override object DefaultNewRowValue
            {
                get
                {
                    // Use the current date and time as the default value.
                    return defVal; // reourne la valeur par defaut...
                }
            }
        }
    }
    3/ le class "oublié" par toi LabelButtonControl
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    namespace ControlLib
    {
        public class LabelButtonControl: LabelButton, IDataGridViewEditingControl
        {
            DataGridView dataGridView;
            private bool valueChanged = false;
            int rowIndex;
           
            public LabelButtonControl()
            { 
            }
    
            // Implements the IDataGridViewEditingControl.EditingControlFormattedValue 
            // property.
            public object EditingControlFormattedValue
            {
                get
                {
                    return this.control_lb.Text;
                }
                set
                {
                    if (value is String)
                    {
                        try
                        {
                            // This will throw an exception of the string is 
                            // null, empty, or not in the format of a date.
                            this.control_lb.Text = (String)value;
                        }
                        catch
                        {
                            // In the case of an exception, just use the 
                            // default value so we're not left with a null
                            // value.
                            this.control_lb.Text = "...";
                        }
                    }
                }
            }
    
            // Implements the 
            // IDataGridViewEditingControl.GetEditingControlFormattedValue method.
            public object GetEditingControlFormattedValue(
                DataGridViewDataErrorContexts context)
            {
                return EditingControlFormattedValue;
            }
    
            // Implements the 
            // IDataGridViewEditingControl.ApplyCellStyleToEditingControl method.
            public void ApplyCellStyleToEditingControl(
                DataGridViewCellStyle dataGridViewCellStyle)
            {
                this.Font = dataGridViewCellStyle.Font;
                this.ForeColor = dataGridViewCellStyle.ForeColor;
                this.BackColor = dataGridViewCellStyle.BackColor;
                this.control_lb.Font = dataGridViewCellStyle.Font;
                this.control_lb.ForeColor = dataGridViewCellStyle.ForeColor;
                this.control_lb.BackColor = dataGridViewCellStyle.BackColor;
            }
    
            // Implements the IDataGridViewEditingControl.EditingControlRowIndex 
            // property.
            public int EditingControlRowIndex
            {
                get
                {
                    return rowIndex;
                }
                set
                {
                    rowIndex = value;
                }
            }
    
            // Implements the IDataGridViewEditingControl.EditingControlWantsInputKey 
            // method.
            public bool EditingControlWantsInputKey(
                Keys key, bool dataGridViewWantsInputKey)
            {
               
                switch (key & Keys.KeyCode)
                {
                    case Keys.Left:
                    case Keys.Up:
                    case Keys.Down:
                    case Keys.Right:
                    case Keys.Home:
                    case Keys.End:
                    case Keys.PageDown:
                    case Keys.PageUp:
                        return true;
                    default:
                        return !dataGridViewWantsInputKey;
                }
            }
    
            public void PrepareEditingControlForEdit(bool selectAll)
            {
                // No preparation needs to be done.
            }
    
            public bool RepositionEditingControlOnValueChange
            {
                get
                {
                    return false;
                }
            }
    
            // Implements the IDataGridViewEditingControl
            // .EditingControlDataGridView property.
            public DataGridView EditingControlDataGridView
            {
                get
                {
                    return dataGridView;
                }
                set
                {
                    dataGridView = value;
                }
            }
    
            public bool EditingControlValueChanged
            {
                get
                {
                    return valueChanged;
                }
                set
                {
                    valueChanged = value;
                }
            }
    
            // Implements the IDataGridViewEditingControl
            // .EditingPanelCursor property.
            public Cursor EditingPanelCursor
            {
                get
                {
                    return base.Cursor;
                }
            }
            protected override void OnTextChanged(EventArgs eventargs)
            {
                // Notify the DataGridView that the contents of the cell
                //     have changed.
                
                valueChanged = true;
                this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
                base.OnTextChanged(eventargs);
            }
        }
    }
    4/ code du usercontrol avec l'adjonction de l'event Label.TextChanged qui doit etre notififie au parent UserControl.TextChanged pour le mettre à jour car le dgv "ecoute" le User.Control LabelButton et il ignore totalement ses "enfants" et ce qu'ils mijotent ..

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
    namespace ControlLib
    {
        public partial class LabelButton : UserControl
        {
     
            public LabelButton()
            {
                InitializeComponent();
                this.control_lb.Text = "...";
                this.control_lb.TextChanged += new EventHandler(control_lb_TextChanged);
            }
     
            void control_lb_TextChanged(object sender, EventArgs e)
            {
                this.OnTextChanged(e);
            }
            private void control_btn_Click(object sender, EventArgs e)
            {
                string fileName = GetFileName();
                if (!String.IsNullOrEmpty(fileName))
                {
                    StreamReader rd = File.OpenText(fileName);
                    this.control_lb.Text=rd.ReadToEnd();
                }
            }
            private string GetFileName()
            {
                string fname = string.Empty;
                OpenFileDialog dlg = new OpenFileDialog();
                dlg.Filter = "files text(*.txt)|*.txt";
                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    fname = dlg.FileName;
                }
                return fname;
            }
        }
    }

    5/class data exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    public class Item
        {
            public int MyProp1 { get; set; }
            public string MyProp2 { get; set; }
        }
        public class Items:List <Item>
        {
            public Items ()
    	    {
                for (int i = 0; i < 10; i++)
                {
                    Item it = new Item() { MyProp1 = 19 * 100, MyProp2 = "nom" + i.ToString() };
                    this.Add(it);
                }
    	    }
     
        }
    6/ form user exemple muni d'un dgv bindé à la liste Items et rajout de la custom colonne par code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
    using ControlLib; // REFERENCE A AJOUTER A LA LIBRAIRIE
    namespace WinCustomColumndDGV
    {
        public partial class Form2 : Form
        {
            private LabelButtonCell ctlCell;
            private LabelButtonColumn ctlColumn;
            private DataGridViewButtonCell btnCell;
            private DataGridViewButtonColumn btnColumn;
            private Items liste;
            public Form2()
            {
                InitializeComponent();
                this.Load += new EventHandler(Form2_Load);
            }
     
            void Form2_Load(object sender, EventArgs e)
            {
                liste = new Items();
                this.DGV.DataSource = liste;
                ctlCell = new LabelButtonCell();
                ctlCell.Style.ForeColor = Color.Black;
                ctlCell.Style.BackColor = Color.WhiteSmoke;
                ctlCell.Style.Font = new Font("Times New Roman", 16.0f, FontStyle.Bold);
                ctlColumn = new LabelButtonColumn();
                ctlColumn.HeaderText = "Commentaire";
                ctlColumn.Name = "Commentaire";
                ctlColumn.CellTemplate = ctlCell;
                ctlCell.ValueType = typeof(string);
     
                this.DGV.Columns.Add(ctlColumn);
     
     
            }
     
     
        }
    }
    Bon code...
      1  0

  3. #3
    Membre du Club
    Homme Profil pro
    Inscrit en
    octobre 2013
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : octobre 2013
    Messages : 143
    Points : 43
    Points
    43
    Par défaut
    Merci beaucoup, j'en demandais pas autant

    Concernant le control d’édition je l'avais vu dans le tuto mais de ce que j'avais pu comprendre c'était pour pouvoir éditer la cellule (comme dans un tableur excel), hors vu que mon DGV n'est qu'en lecture seule je m'étais dit que je n'avais pas besoin de ça.

    Pour le clique sur le bouton j'avais déjà mis en place l'appel d'une Form d'édition du commentaire (avec le choix de suppression, save et cancel) mais ton exemple va beaucoup m'aider.

    Je ne vais pas pouvoir tester cela de suite mais je m'y tâcherai en fin de semaine pour donner des nouvelles.

    Merci encore
      0  0

  4. #4
    Membre du Club
    Homme Profil pro
    Inscrit en
    octobre 2013
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : octobre 2013
    Messages : 143
    Points : 43
    Points
    43
    Par défaut
    Bonjour

    Désolé pour mon retour tardif ^^

    J'ai pu tester ta solution mais malheureusement je n'arrive pas à la faire fonctionner.

    Dans la partie LabelButtonCell dans EditType tu as laissé "MyContainerControl" j'ai supposé qu'il s'agissait de LabelButtonControl.

    Quand je lance le programme, la colonne "Commentaire" affiche des cellules vides et quand je clique dessus je tombe sur une exception "An unhandled exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll"

    Je me suis dit que ça venait peut-être de l'ouverture du fichier texte du coup je l'ai remplacé par l'ouverture d'une autre form mais ça ne change rien.

    Donc je suis un peu perdu et j'ai quelques questions qui me vient :
    - J'ai essayé d'ajouter la colonne manuellement dans le form du DGV via l'édition de colonne et en choisissant LabelButtonColumn en ColumnType. Le label semble bien s'afficher mais pas le bouton..
    Nom : form1.png
Affichages : 44
Taille : 5,7 Ko
    Ce qui est attendu : Nom : LabelButton.png
Affichages : 44
Taille : 1,2 Ko

    - Dans la form de test tu as ajouté deux variables btnCell et btnColumn mais elles ne sont pas utilisées, c'est normal ?

    Si jamais voici le projet complet juste avec le control et la form de test mais je n'ai rien changé en plus.
    ControlLib.zip

    Je te remercie d'avance pour ton aide
      0  0

  5. #5
    Membre du Club
    Homme Profil pro
    Inscrit en
    octobre 2013
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : octobre 2013
    Messages : 143
    Points : 43
    Points
    43
    Par défaut
    Me revoilà

    Après moultes recherches j'ai trouvé ce post qui m'a bien aidé.

    En gros il me manquait la partie où l'on dessine le control.

    J'ai donc modifié la classe "LabelButtonCell" comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    public class LabelButtonCell : DataGridViewTextBoxCell
        {
            private LabelButtonControl lbControl;
            private string defVal = "..."; //valeur par defaut affichée lorsque on entre en mode edition (double clic sur cellule du dgv)
            public LabelButtonCell()
                : base()
            { lbControl = new LabelButtonControl(); }
     
            public override void InitializeEditingControl(int rowIndex, object
                initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
            {
                // Set the value of the editing control to the current cell value.
                base.InitializeEditingControl(rowIndex, initialFormattedValue,
                    dataGridViewCellStyle);
                LabelButton ctl =
                    DataGridView.EditingControl as LabelButton;
                // Use the default row value when Value property is null.
                if (this.Value == null)
                {
                    ctl.control_lb.Text = (string)this.DefaultNewRowValue;
                }
                else
                {
                    ctl.control_lb.Text = (string)this.Value;
                }
            }
     
            protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
            {
                lbControl.Size = cellBounds.Size;
                lbControl.Location = cellBounds.Location;
     
                if (!(this.DataGridView.Controls.Contains(lbControl)))
                {
                    this.DataGridView.Controls.Add(lbControl);
                }
     
                foreach (Control ctr in DataGridView.Controls)
                {
                    ctr.Refresh();
                    //Je ne comprend pas mais ca supprime mes problèmes de refresh sans effet de bord
                    if (ctr.Size != lbControl.Size)
                        DataGridView.Controls.Remove(ctr);
     
                }
     
                base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
            }
     
            public override Type EditType
            {
                get
                {
                    // Return the type of the editing control that LabelButtonCell uses.
                    return typeof(LabelButtonControl);
                }
            }
     
            public override Type ValueType
            {
                get
                {
                    // Return the type of the value that CalendarCell contains.
     
                    return typeof(string);
                }
            }
     
            public override object DefaultNewRowValue
            {
                get
                {
                    // Use the current date and time as the default value.
                    return defVal; // reourne la valeur par defaut...
                }
            }
        }
    Ça donne cela : Nom : goodForm.png
Affichages : 40
Taille : 12,9 Ko

    Il y a quand même quelques soucis de rafraîchissement du control malgré l'amélioration porté par l'utilisateur du post ci-dessus.

    Je continu mes recherches
      0  0

  6. #6
    Membre expert
    Inscrit en
    avril 2008
    Messages
    2 244
    Détails du profil
    Informations personnelles :
    Âge : 59

    Informations forums :
    Inscription : avril 2008
    Messages : 2 244
    Points : 3 769
    Points
    3 769
    Par défaut
    bonjour

    Dans la partie LabelButtonCell dans EditType tu as laissé "MyContainerControl" j'ai supposé qu'il s'agissait de LabelButtonControl.
    Effectivement .Tu as rectifié comme il faut...!
    - Dans la form de test tu as ajouté deux variables btnCell et btnColumn mais elles ne sont pas utilisées, c'est normal ?
    Ils sont inutiles car j'ai copier-coller les déclarations d'un autre projet ,et ceci montre que le copier -coller joue des tours & qu'il est à éviter ...

    Pour le reste le code fonctionne perfectly chez moi comme suit:
    -l’apparence de la cellule: on voit un "vide" à gauche (le label) et un button ("...") dans la cellule
    -1er clic on entre en mode "édition"
    -2er clic sur le bouton
    -suit une boite de dialogue d'invite à choisir un fichier texte...
    -on quitte la cellule ,le texte "saisi" s'affiche dans le label vide avec "ellipsis" si la "column" a une largeur insuffisante...
    bon code...
      0  0

  7. #7
    Membre du Club
    Homme Profil pro
    Inscrit en
    octobre 2013
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : octobre 2013
    Messages : 143
    Points : 43
    Points
    43
    Par défaut
    Bonjour

    Merci pour ton retour. J'ai à nouveau testé ta solution et j'ai réussi à la faire fonctionner
    Nom : edit.png
Affichages : 32
Taille : 4,9 Ko

    Après le soucis c'est que mon DataGridView est en ReadOnly par défaut car il sert uniquement pour de la consultation. Et à cause de ça le clic dans la cellule pour ouvrir l'édition ne marche pas. D'ailleurs ça m'embêterai de devoir faire un clic en plus pour que l'utilisateur puisse voir le commentaire.
    Y-a-t-il un moyen pour afficher le control directement sans passer par le clic de l'édition ?

    Concernant l'autre solution, elle me permet d'avoir directement le control d'afficher dans la cellule. Cependant, il y a un gros problème de dessin du control quand je scroll...
    Nom : 2019-11-08_11-14-14.gif
Affichages : 30
Taille : 1,45 Mo

    Il y-t-il un moyen de mettre un double buffer sur ce control ? (Je l'ai déjà fait pour le DGV car j'ai une grande quantité de ligne et ça m'a permis de corriger la lenteur du scroll).

    Je continu mon investigation ^^
      0  0

  8. #8
    Membre du Club
    Homme Profil pro
    Inscrit en
    octobre 2013
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : octobre 2013
    Messages : 143
    Points : 43
    Points
    43
    Par défaut
    Me revoilà ^^

    Finalement ta solution me convient parfaitement. J'avais pas tilté que lorsque le label à une valeur elle est bien affichée puis si l'on veut la changer il suffit de double cliquer pour afficher le bouton. Ce que tu avais expliqué juste avant... (c'est vendredi :p)
    J'ai donc enlevé le ReadOnly sur mon DGV et j'ai mis toutes mes colonnes sauf celle du commentaire en ReadOnly true.

    Du coup je vais voir pour l'utiliser à ma sauce

    Pour l'autre solution je la laisse de côté car malgré le fait d'ajouter un buffer au control l'application devient très lente donc ça ne vaut pas le coup. Mais si jamais quelqu'un a une solution n'hésitez pas, ça pourrait aider d'autre personnes

    Merci

    ---EDIT---
    Je me pose une question :
    Comment je fais pour récupérer l'event Click du bouton dans mon programme principale ? Car là on dit directement quoi faire dans le control ce que doit faire le bouton mais j'aimerai laisser ça libre de choix dans le programme principale.
    Mon but étant d'ouvrir une autre form venant du programme pour l'édition du label.
      0  0

  9. #9
    Membre du Club
    Homme Profil pro
    Inscrit en
    octobre 2013
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : octobre 2013
    Messages : 143
    Points : 43
    Points
    43
    Par défaut
    Bonjour

    Du coup, j'ai créé un event dans le control avec lequel je m'inscris dans la form mais cela ne fonctionne pas. Lorsque je clique sur le bouton du control je n'enclenche pas l'événement.

    Classe LabelButton du control :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public partial class LabelButton: UserControl
        {
            public event EventHandler ButtonClick;
    
            public LabelButton()
            {
                InitializeComponent();
                this.control_lb.Text = "...";
                this.control_lb.TextChanged += new EventHandler(control_lb_TextChanged);
                this.button1.Click += Button1_Click;
            }
    
            protected void Button1_Click(object sender, EventArgs e)
            {
                ButtonClick?.Invoke(this, e);
            }
    
            void control_lb_TextChanged(object sender, EventArgs e)
            {
                this.OnTextChanged(e);
            }
        }
    Dans la form :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    // Déclaration
    LabelButton lb = new LabelButton();
     
    // Dans le constructeur
     this.lb.ButtonClick += LabelButton_ButtonClick;
     
    // Méthode 
    private void LabelButton_ButtonClick(object sender, EventArgs e)
    {
    // ...
    }
    J'ai regardé sur des forums et la plupart montre cette même solution. Le seul truc qui me perturbe c'est de déclarer un objet LabelButton qui n'est pas rattaché au DGV pour récupérer l'event...
      0  0

  10. #10
    Membre du Club
    Homme Profil pro
    Inscrit en
    octobre 2013
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : octobre 2013
    Messages : 143
    Points : 43
    Points
    43
    Par défaut
    Re

    J'ai trouvé la solution !

    En gros j'initialise un objet de type LabelButtonControl dans l'événement EditingControlShowing du DGV puis je subscribe l'event ButtonClick.

    Dans la form :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    LabelButtonControl c;
     
    private void _DataGridViewGTR_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
            {
                if (e.Control is LabelButtonControl)
                {
                    c = (LabelButtonControl)e.Control;
                    c.ButtonClick += C_ButtonClick;
                }
            }
     
    private void C_ButtonClick(object sender, EventArgs e)
    {
    // ...
    // Je fais un try catch finally et dans le finally j'ajoute : c.ButtonClick -= C_ButtonClick;
    }
    Voilà

    J'ai enfin mon control customisé opérationnel ! Je vais donc clore le sujet mais n'hésitez pas à donner vos avis si jamais ça peu aider d'autres personnes

    Merci
      0  0

  11. #11
    Membre du Club
    Homme Profil pro
    Inscrit en
    octobre 2013
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : octobre 2013
    Messages : 143
    Points : 43
    Points
    43
    Par défaut
    Finalement je me heurte à un nouveau problème.

    Maintenant que le control fonctionne, j'aimerai pouvoir initialiser les labels de chaque control qui se trouve dans mon DGV.

    Cependant, lorsque je fais ça j'ai une erreur de ce type au moment où je veux changer le CurrentCell :
    "L'opération n'est pas valide, car elle se traduit par un appel réentrant à la fonction SetCurrentCellAddressCore."

    Voici mon code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    private void AddExistingCommentToControl()
            {
                List<Comment> cmtList = new List<Comment>(_cmtBL.GetComments); // Ma liste de commentaires
     
                foreach (Comment cmt in cmtList)
                {
                    foreach (DataGridViewRow row in _DataGridViewGTR.Rows)
                    {
                        if (cmt.Id.Equals(row.Cells["Id"].Value.ToString()))
                        {
                            foreach (DataGridViewCell cell in row.Cells)
                            {
                                if (cell.EditType.Name.Equals("LabelButtonControl"))
                                {
                                    _DataGridViewGTR.CurrentCell = cell;
                                    _DataGridViewGTR.BeginEdit(true);
                                    cell.InitializeEditingControl(row.Index, cmt.Comment.ToString(), cell.Style);
                                    _DataGridViewGTR.BeginEdit(false);
                                }
                            }
                            //_DataGridViewGTR.CurrentCell = null; // Marche pas
                        }
                    }
                }
            }
    Si vous avez une idée de comment faire ce que je souhaite je suis preneur ^^

    Merci d'avance.
      0  0

  12. #12
    Membre expert
    Inscrit en
    avril 2008
    Messages
    2 244
    Détails du profil
    Informations personnelles :
    Âge : 59

    Informations forums :
    Inscription : avril 2008
    Messages : 2 244
    Points : 3 769
    Points
    3 769
    Par défaut
    re-bonjour

    Tout cela frise "la navigation à vue" et le "most simplest code" est le suivant revu pour :
    1/ pour initialiser les labels :
    2/ pour gérer le "clic" du bouton et ouvrir une boite de dialogue à l’extérieur pour saisir un texte de commentaire :

    1/ code revu du UserControl :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
     
    namespace ControlLib
    {
        public partial class LabelButton : UserControl
        {
            public LabelButton()
            {
                InitializeComponent();
                this.control_lb.Text = "...";
                this.control_lb.TextChanged += new EventHandler(control_lb_TextChanged);
                this.control_btn.Click +=new EventHandler(control_btn_Click);
            }
     
            void control_lb_TextChanged(object sender, EventArgs e)
            {
                this.OnTextChanged(e);
            }
            private void control_btn_Click(object sender, EventArgs e)
            {
                //string fileName = GetFileName();
                //if (!String.IsNullOrEmpty(fileName))
                //{
                //    StreamReader rd = File.OpenText(fileName);
                //    this.control_lb.Text=rd.ReadToEnd();
                //}
     
            }
     
            //private string GetFileName()
            //{
            //    string fname = string.Empty;
            //    OpenFileDialog dlg = new OpenFileDialog();
            //    dlg.Filter = "files text(*.txt)|*.txt";
            //    if (dlg.ShowDialog() == DialogResult.OK)
            //    {
            //        fname = dlg.FileName;
            //    }
            //    return fname;
            //}
        }
    }
    code revu du Form User:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
     
    namespace WinTest
    {
        public partial class Form1 : Form
        {
            private LabelButtonCell ctlCell;
            private LabelButtonColumn ctlColumn;
            private Items liste;
            public Form1()
            {
                InitializeComponent();
                this.Load += new EventHandler(Form1_Load);
                this.dataGridView1.EditingControlShowing += new DataGridViewEditingControlShowingEventHandler(dataGridView1_EditingControlShowing);
            }
            void Form1_Load(object sender, EventArgs e)
            {
                liste = new Items();
                this.dataGridView1.DataSource = liste;
                ctlCell = new LabelButtonCell();
                ctlCell.Style.ForeColor = Color.Black;
                ctlCell.Style.BackColor = Color.Yellow;
                ctlCell.Style.Font = new Font("Times New Roman", 12.0f, FontStyle.Italic);
                ctlColumn = new LabelButtonColumn();
                ctlColumn.HeaderText = "Commentaire";
                ctlColumn.Name = "Commentaire";
                ctlColumn.CellTemplate = ctlCell;
                ctlColumn.ValueType = typeof(string);
     
                this.dataGridView1.Columns.Add(ctlColumn);
                AddExistingCommentToControl();
     
            }
            void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
            {
                Control  c = e.Control as Control ;
                if (c == null) return;
                if (c.GetType() == typeof(LabelButtonControl))
                {
                    LabelButtonControl lblCtl = (LabelButtonControl)c;
                    lblCtl.control_btn.Click -= new EventHandler(control_btn_Click); 
                    lblCtl.control_btn.Click += new EventHandler(control_btn_Click);
                }
     
            }
     
            void control_btn_Click(object sender, EventArgs e)
            {
                Button btn = sender as Button;
                FormDialog frm = new FormDialog();
                frm.ShowDialog();
                if (frm.DialogResult == DialogResult.OK )
                {
                    TableLayoutPanel tablePanel = btn.Parent as TableLayoutPanel;
                    LabelButtonControl lblCtl =tablePanel.Parent as LabelButtonControl;
                    lblCtl.control_lb.Text = frm.MyComment;
                    frm.Dispose();
     
                }
                else
                {
                    frm.Dispose();
                }
            }
     
            private void AddExistingCommentToControl()
            {
                List<string> cmtList = new List<string>(); // Ma liste de commentaires
     
                    //most simplest code
                    foreach (DataGridViewRow row in dataGridView1.Rows)
                    {
                            foreach (DataGridViewCell cell in row.Cells)
                            {
                                if (cell.EditType.Name.Equals("LabelButtonControl"))
                                {
                                   cell.Value="Ali Baba ";
                                }
                            }
                    }
            }
     
        }
    }
    code de la boite dialogue :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    namespace WinTest
    {
        //  ajouter un control textbox denommé txComment
        public partial class FormDialog : Form
        {
            public string MyComment
            {
                get { return this.txComment.Text ; }
                set { this.txComment.Text = value; }
            }
     
            public FormDialog()
            {
                InitializeComponent();
                this.AcceptButton = btnOK;
                this.CancelButton = btnCancel;
            }
     
            private void btnOK_Click(object sender, EventArgs e)
            {
                this.DialogResult = DialogResult.OK;
            }
     
            private void btnCancel_Click(object sender, EventArgs e)
            {
                this.DialogResult = DialogResult.Cancel;
              ;
            }
        }
    }
    bon code...
      0  0

  13. #13
    Membre du Club
    Homme Profil pro
    Inscrit en
    octobre 2013
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : octobre 2013
    Messages : 143
    Points : 43
    Points
    43
    Par défaut
    Bonjour

    Merci beaucoup pour ton aide ! J'étais tellement persuadé qu'il fallait que j'initialise avec le label du control directement que je n'ai même pas pensé à tester avec la valeur de la cellule...

    Du coup j'ai pu simplifier mon code également grâce à toi ^^

    Tout fonctionne parfaitement. C'est la première fois que je fais un control custom et j'ai bien compris les bases maintenant. Ça aidera sûrement d'autres personnes aussi par la suite

    Je peux dire que ce sujet est finalement clos.

    Merci
      0  0

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. difference entre Custom Control et User Control
    Par ammar.dev dans le forum C#
    Réponses: 2
    Dernier message: 07/09/2016, 09h10
  2. Liste box Specializée, Custom Control ou user control?
    Par dominiqueFaure dans le forum Windows Presentation Foundation
    Réponses: 2
    Dernier message: 04/02/2011, 10h29
  3. [C#] User Control dynamic
    Par Erakis dans le forum ASP.NET
    Réponses: 10
    Dernier message: 21/10/2004, 19h54
  4. [C#] DateTimePicker web user control
    Par titi29 dans le forum ASP.NET
    Réponses: 8
    Dernier message: 29/06/2004, 19h38
  5. [VB.NET] Provoquer le rechargement d'un user control..
    Par didoboy dans le forum ASP.NET
    Réponses: 7
    Dernier message: 30/04/2004, 15h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo