web-dev-qa-db-fra.com

Déclenchement d'un événement modifié dans une case à cocher dans DataGridView

J'ai une vue de grille avec une colonne de case à cocher et je veux déclencher un événement de dessin dès que la valeur de la cellule est modifiée. J'ai essayé le ValueChaged et le CellEndEdit et BeginEdit, et ai choisi le mode de sélection comme CellSelect. En ce qui concerne les 2 premiers événements, l'événement a été déclenché à la fin du mode édition, comme si vous sortiez de la cellule en cours ou que vous alliez et venait. C'est juste un comportement étrange. 

Existe-t-il quelque chose qui déclenche l'événement dans la vue de grille dès que la valeur de la cellule est modifiée?

Meilleures salutations,

29
mustafabar

Un de mes collègues recommande de piéger l'événement CurrentCellDirtyStateChanged. Voir http://msdn.Microsoft.com/en-us/library/system.windows.forms.datagridview.currentcelldirtystatechanged.aspx

23
user120381

J'utilise l'événement CellContentClick, qui s'assure que l'utilisateur a coché la case. Il ne se déclenche pas plusieurs fois, même si l'utilisateur reste dans la même cellule. Le seul problème est que la valeur n'est pas mise à jour et renvoie toujours "false" pour non cochée. L'astuce consiste à utiliser la propriété .EditedFormattedValue de la cellule au lieu de la propriété Value. EditedFormattedValue suivra avec la coche et correspond à ce que l’on voudrait que la Valeur l’ait quand le CellContentClick est déclenché.

Pas besoin de minuterie, pas besoin de trucs fantaisistes, utilisez simplement l'événement CellContentClick et inspectez la propriété EditedFormattedValue pour indiquer l'état dans lequel la case à cocher est en train d'être activée. Si EditedFormattedValue = true, la case à cocher est cochée.

32
Christo

Une autre méthode consiste à gérer l'événement CellContentClick (qui ne vous donne pas la valeur actuelle dans la propriété Value de la cellule), appelez grid.CommitEdit (DataGridViewDataErrorContexts.Commit) pour mettre à jour la valeur qui sera ensuite déclenchée par CellValueChanged, où valeur réelle (c.-à-d. correcte) DataGridViewCheckBoxColumn.

private void grid_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
   grid.CommitEdit(DataGridViewDataErrorContexts.Commit);
}

private void grid_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    // do something with grid.Rows[e.RowIndex].Cells[e.ColumnIndex].Value
}

Cadre cible .NET: 2.0

20
Stuart

J'ai eu le même problème, mais est venu avec une solution différente:

Si vous faites la colonne ou la grille entière "Read Only" afin que l'utilisateur clique sur la case à cocher, il ne change pas de valeur.

Heureusement, l'événement DataGridView.CellClick est toujours déclenché . Dans mon cas, je procède comme suit dans l'événement cellClick:

if (jM_jobTasksDataGridView.Columns[e.ColumnIndex].CellType.Name == "DataGridViewCheckBoxCell")

Mais vous pouvez vérifier le nom de la colonne si vous avez plusieurs colonnes à cocher.

Je fais ensuite toutes les modifications/sauvegarde de l'ensemble de données moi-même.

4
James

Je l'ai finalement implémenté de cette façon

  private void dataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
    {

        if (e.ColumnIndex >= 0 && e.RowIndex >= 0)
        {
            if (dataGridView1[e.ColumnIndex, e.RowIndex].GetContentBounds(e.RowIndex).Contains(e.Location))
            {
                cellEndEditTimer.Start();
            }
        }

    }

    private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
    { /*place your code here*/}


    private void cellEndEditTimer_Tick(object sender, EventArgs e)
    {
        dataGridView1.EndEdit();
        cellEndEditTimer.Stop();
    }
4
mustafabar

Essayez de vous connecter à l'événement CellContentClick. Le DataGridViewCellEventArgs aura un ColumnIndex et un RowIndex afin que vous puissiez savoir si un ChecboxCell a été cliqué. La bonne chose à propos de cet événement est qu'il ne se déclenchera que si la case à cocher elle-même a été cochée. Si vous cliquez sur la zone blanche de la cellule autour de la case à cocher, elle ne se déclenchera pas. De cette façon, vous êtes quasiment assuré que la valeur de la case à cocher a été modifiée lors du déclenchement de cet événement. Vous pouvez ensuite appeler Invalidate () pour déclencher votre événement de dessin, ainsi qu'un appel à EndEdit () pour déclencher la fin de la modification de la ligne si vous en avez besoin.

4
BFree

L'événement "EditingControlShowing" ne se déclenche pas lors du changement de valeur de case à cocher. Parce que le style d’affichage de la case à cocher ne change pas.

La solution de contournement que j'ai utilisée est la suivante. (J'ai utilisé l'événement CellContentClick)

    private void gGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
        if (string.Compare(gGridView1.CurrentCell.OwningColumn.Name, "CheckBoxColumn") == 0)
        {
            bool checkBoxStatus = Convert.ToBoolean(gGridView1.CurrentCell.EditedFormattedValue);
            //checkBoxStatus gives you whether checkbox cell value of selected row for the
            //"CheckBoxColumn" column value is checked or not. 
            if(checkBoxStatus)
            {
                //write your code
            }
            else
            {
               //write your code
            }
        }
    }

Ce qui précède a fonctionné pour moi. S'il vous plaît laissez-moi savoir si besoin de plus d'aide.

1
Yamanappa

cellEndEditTimer.Start ();

cette ligne fait que datagridview met à jour la liste des cases cochées

Je vous remercie.

1
Leandro

J'ai trouvé une solution simple.

Il suffit de changer le focus de la cellule après avoir cliqué sur la cellule.

private void DGV_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    if (e.ColumnIndex == "Here checkbox column id or name") {
        DGV.Item(e.ColumnIndex, e.RowIndex + 1).Selected = true;
        //Here your code

    }
}

N'oubliez pas de vérifier si la colonne de votre index (ckeckbox + 1) existe.

1
Mauricio de León

Utilisez ce code lorsque vous souhaitez utiliser l'événement checkedChanged dans la vue DataGrid:

private void grdBill_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    grdBill.CurrentCell =  grdBill.Rows[grdBill.CurrentRow.Index].Cells["gBillNumber"];
}

private void grdBill_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    calcBill();
}

private void calcBill()
{
    listBox1.Items.Clear();
    for (int i = 0; i < grdBill.Rows.Count - 1; i++)
    {
        if (Convert.ToBoolean(grdBill.Rows[i].Cells["gCheck"].Value) == true)
        {
            listBox1.Items.Add(grdBill.Rows[i].Cells["gBillNumber"].Value.ToString());
        }
    }
}

Ici, grdBill = DataGridView1, gCheck = CheckBox in GridView(First Column), gBillNumber = TextBox dans la grille (deuxième colonne).

Ainsi, lorsque nous voulons déclencher un événement checkchanged pour chaque clic, commencez par CellContentClick, il sera déclenché lorsque l'utilisateur cliquera sur la zone de texte, puis la cellule actuelle sera déplacée vers la colonne suivante. Indiquez si la case à cocher est cochée et ajoutez le "gBillNumber" dans la liste (dans la fonction calcBill).

0
Jegan

J'ai trouvé une combinaison des deux premières réponses m'a donné ce dont j'avais besoin. J'ai utilisé l'événement CurrentCellDirtyStateChanged et inspecté EditedFormattedValue.

private void dgv_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
   DataGridView dgv = (DataGridView)sender;
   DataGridViewCell cell = dgv.CurrentCell;
   if (cell.RowIndex >= 0 && cell.ColumnIndex == 3) // My checkbox column
     {
        // If checkbox checked, copy value from col 1 to col 2
        if (dgv.Rows[cell.RowIndex].Cells[cell.ColumnIndex].EditedFormattedValue != null && dgv.Rows[cell.RowIndex].Cells[cell.ColumnIndex].EditedFormattedValue.Equals(true))
        {
           dgv.Rows[cell.RowIndex].Cells[1].Value = dgv.Rows[cell.RowIndex].Cells[2].Value;
        }
     }
}
0
Mike Pollitt

Travailler avec un contrôle indépendant (c’est-à-dire que je gère le contenu par programmation), sans EndEdit (), il n’appelait que CurrentCellDirtyStateChanged une fois, puis jamais plus; mais j'ai trouvé qu'avec le EndEdit () CurrentCellDirtyStateChanged s'appelait deux fois (le second étant probablement causé par le EndEdit () mais je n'ai pas vérifié), j'ai donc fait ce qui suit, ce qui a fonctionné mieux pour moi:

    bool myGridView_DoCheck = false;
    private void myGridView_CurrentCellDirtyStateChanged(object sender, EventArgs e)
    {
        if (!myGridView_DoCheck)
        {
            myGridView_DoCheck = true;
            myGridView.EndEdit();
            // do something here
        }
        else
            myGridView_DoCheck = false;
    }
0

Chacune des réponses CellClick et CellMouseClick est fausse, car vous pouvez modifier la valeur de la cellule avec le clavier et l'événement ne se déclenchera pas. De plus, CurrentCellDirtyStateChanged n'est déclenché qu'une seule fois, ce qui signifie que si vous cochez/décochez la même case plusieurs fois, vous ne recevrez qu'un seul événement. La combinaison de certaines des réponses ci-dessus donne la solution simple suivante:

private void dgvList_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
    if (dgvList.CurrentCell is DataGridViewCheckBoxCell)
        dgvList.CommitEdit(DataGridViewDataErrorContexts.Commit);
}

private void dgvList_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    // Now this will fire immediately when a check box cell is changed,
    // regardless of whether the user uses the mouse, keyboard, or touchscreen.
    //
    // Value property is up to date, you DO NOT need EditedFormattedValue here.
}
0
Eric Lindsey