web-dev-qa-db-fra.com

Les colonnes CheckBoxField dans ASP.NET GridView sont désactivées même si ReadOnly est défini sur false

J'ai un GridView avec deux colonnes CheckBoxField. Ils ont tous les deux la propriété ReadOnly définie sur false, mais le code html généré pour eux a l'attribut disabled = "disabled". La valeur ne peut donc pas être modifiée.

Exemple HTML généré:

<span disabled="disabled"><input id="ctl00_ContentBody_GridView_ctl02_ctl01" type="checkbox" name="ctl00$ContentBody$GridView$ctl02$ctl01" checked="checked" disabled="disabled" /></span>

Quelqu'un peut-il dire comment le comprendre?

25
brain_pusher

C'est par conception; les lignes d'un GridView ne sont pas modifiables par défaut.

Vous pouvez résoudre ce problème de deux manières:

1. Ajouter un lien Modifier

Dans votre balise GridView, ajoutez AutoGenerateEditButton="True". Lorsque votre GridView s'affiche dans le navigateur, vous devriez maintenant trouver un lien hypertexte intitulé "Modifier". Si vous cliquez dessus, les champs de votre GridView deviendront modifiables et le lien Modifier deviendra deux liens, l'un pour enregistrer vos modifications dans la base de données et l'autre pour les ignorer. En utilisant cette méthode, toute la plomberie pour câbler les modifications du GridView à la base de données peut être effectuée pour vous, en fonction de la façon dont vous effectuez la liaison de données. Cet exemple utilise un contrôle SqlDataSource.
alt text
(source: philippursglove.com )

alt text

2. Ajoutez un TemplateField avec un CheckBox à l'intérieur

À l'intérieur de <columns>, vous pouvez ajouter des TemplateFields que vous définissez vous-même la liaison de données, par exemple.

<asp:TemplateField HeaderText="Discontinued">  
    <ItemTemplate>  
        <asp:CheckBox runat="server" ID="DiscontinuedCheckBox" 
            Checked='<%# Eval("Discontinued")  %>' AutoPostback="true" 
            OnCheckedChanged="DiscontinuedCheckBox_CheckedChanged" />  
    </ItemTemplate>  
</asp:TemplateField>

alt text
(source: philippursglove.com )

Cette case à cocher sera activée, mais vous devez effectuer vous-même le travail pour refléter les modifications apportées à la base de données. C'est simple tant que vous pouvez obtenir une clé de base de données, car vous devrez exécuter une instruction UPDATE à un moment donné et vous voulez l'exécuter sur la bonne ligne! Voici deux façons de procéder:

Dans votre balise Gridview, ajoutez DataKeyNames="MyDatabasePrimaryKey". Ensuite, dans votre gestionnaire d'événements CheckedChanged, vous devez trouver dans quelle ligne vous vous trouvez et le rechercher dans le tableau DataKeys.

protected void DiscontinuedCheckBox_CheckedChanged(object sender, EventArgs e)
{
    CheckBox DiscontinuedCheckBox;
    SqlConnection conn;
    SqlCommand cmd;
    int productId;
    GridViewRow selectedRow;

    // Cast the sender object to a CheckBox
    DiscontinuedCheckBox = (CheckBox)sender;

    // We can find the row we clicked the checkbox in by walking up the control tree
    selectedRow = (GridViewRow)DiscontinuedCheckBox.Parent.Parent;

    // GridViewRow has a DataItemIndex property which we can use to look up the DataKeys array
    productId = (int)ProductGridView.DataKeys[selectedRow.DataItemIndex].Value;

    using (conn = new SqlConnection(ProductDataSource.ConnectionString))
    {
        cmd = new SqlCommand();
        cmd.Connection = conn;
        cmd.CommandType = CommandType.Text;
        if (DiscontinuedCheckBox.Checked)
        {
            cmd.CommandText = "UPDATE Products SET Discontinued = 1 WHERE ProductId = " + ProductId.ToString();
        }
        else
        {
            cmd.CommandText = "UPDATE Products SET Discontinued = 0 WHERE ProductId = " + ProductId.ToString();
        }
        conn.Open();
        cmd.ExecuteNonQuery();
        conn.Close();
    }
}

Ou, vous pouvez ajouter la clé dans un contrôle HiddenField:

<asp:TemplateField HeaderText="Discontinued">  
    <ItemTemplate>  
        <asp:hiddenfield runat="server" id="ProductIdHiddenField" 
            Value='<%# Eval("ProductID") %>' />
        <asp:CheckBox runat="server" ID="DiscontinuedCheckBox" 
            Checked='<%# Eval("Discontinued")  %>' 
            AutoPostback="true"
            OnCheckedChanged="DiscontinuedCheckBox_CheckedChanged" />  
    </ItemTemplate>  
</asp:TemplateField>

Code:

protected void DiscontinuedCheckBox_CheckedChanged(object sender, EventArgs e)
{
    CheckBox DiscontinuedCheckBox;
    HiddenField ProductIdHiddenField;

    DiscontinuedCheckBox = (CheckBox)sender;

    ProductIdHiddenField = (HiddenField)DiscontinuedCheckBox.Parent.FindControl("ProductIdHiddenField");

    using (conn = new SqlConnection(ProductDataSource.ConnectionString))
    {
    ...
    if (DiscontinuedCheckBox.Checked)
    {
        cmd.CommandText = "UPDATE Products SET Discontinued = 1 WHERE ProductId = " + ProductIdHiddenField.Value;
    }
    ...
    }
41
PhilPursglove

La solution PhilPursglove fonctionne pour moi (même dans une vue grivview imbriquée). Je vous remercie!

Mon code complet (modifié pour obtenir également le grivview en utilisant l'arborescence de contrôle, car je ne peux pas accéder directement au netest gridview à cause de la création dynamique):

protected void Cb_IsApprovedByManagement_CheckChanged(object sender, EventArgs e)
    {
        CheckBox cb = (CheckBox)sender;

        // find the row we clicked the checkbox in by walking up the control tree
        GridViewRow selectedRow = (GridViewRow)cb.Parent.Parent;
        GridView gridView = (GridView)selectedRow.Parent.Parent;

        //  look up the DataKeys array
        int QuestionID_Current = (int)gridView.DataKeys[selectedRow.DataItemIndex].Value;

        // change value
        QuestionManager.ToggleActivity(QuestionManager.GetQuestion(QuestionID_Current));
1
J_Reed