J'essaie d'obtenir un ASP.NET 3.5 GridView pour afficher une valeur sélectionnée sous forme de chaîne lors de l'affichage, et pour afficher un DropDownList pour me permettre de choisir une valeur dans une liste d'options donnée lors de la modification. Semble assez simple?
Ma grille ressemble à ceci (simplifié):
<asp:GridView ID="grvSecondaryLocations" runat="server"
DataKeyNames="ID" OnInit="grvSecondaryLocations_Init"
OnRowCommand="grvSecondaryLocations_RowCommand"
OnRowCancelingEdit="grvSecondaryLocations_RowCancelingEdit"
OnRowDeleting="grvSecondaryLocations_RowDeleting"
OnRowEditing="grvSecondaryLocations_RowEditing"
OnRowUpdating="grvSecondaryLocations_RowUpdating" >
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="lblPbxTypeCaption" runat="server"
Text='<%# Eval("PBXTypeCaptionValue") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="ddlPBXTypeNS" runat="server"
Width="200px"
DataTextField="CaptionValue"
DataValueField="OID" />
</EditItemTemplate>
</asp:TemplateField>
</asp:GridView>
La grille s'affiche OK quand elle n'est pas en mode édition - le type PBX sélectionné affiche sa valeur dans le contrôle asp: Label. Pas de surprise là-bas.
Je charge la liste des valeurs de DropDownList dans un membre local appelé _pbxTypes
dans l'événement OnLoad
du formulaire. J'ai vérifié cela - cela fonctionne, les valeurs sont là.
Maintenant, mon défi est: lorsque la grille passe en mode édition pour une ligne particulière, je dois lier la liste des PBX stockés dans _pbxTypes
.
Assez simple, je pensais - il suffit de saisir l'objet liste déroulante dans l'événement RowEditing
et de joindre la liste:
protected void grvSecondaryLocations_RowEditing(object sender, GridViewEditEventArgs e)
{
grvSecondaryLocations.EditIndex = e.NewEditIndex;
GridViewRow editingRow = grvSecondaryLocations.Rows[e.NewEditIndex];
DropDownList ddlPbx = (editingRow.FindControl("ddlPBXTypeNS") as DropDownList);
if (ddlPbx != null)
{
ddlPbx.DataSource = _pbxTypes;
ddlPbx.DataBind();
}
.... (more stuff)
}
Le problème est - je ne reçois jamais rien de l'appel FindControl
- semble que le ddlPBXTypeNS
n'existe pas (ou ne peut pas être trouvé).
Qu'est-ce que je rate?? Ça doit être quelque chose de vraiment stupide ... mais jusqu'à présent, tout mon googler, lire sur les contrôles GridView et demander à mes amis n'a pas aidé.
Qui peut repérer le lien manquant? ;-)
Assez facile ... Vous vous trompez, car par cet événement, le contrôle n'est pas là:
protected void gv_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow &&
(e.Row.RowState & DataControlRowState.Edit) == DataControlRowState.Edit)
{
// Here you will get the Control you need like:
DropDownList dl = (DropDownList)e.Row.FindControl("ddlPBXTypeNS");
}
}
Autrement dit, il ne sera valide que pour un DataRow
(la ligne contenant des données), et s'il est en mode Edit ... car vous n'éditez qu'une ligne à la fois. La fonction e.Row.FindControl("ddlPBXTypeNS")
ne trouvera que le contrôle souhaité.
J'utilise un ListView au lieu d'un GridView en 3.5. Lorsque l'utilisateur souhaite modifier, j'ai défini l'élément sélectionné de la liste déroulante sur la valeur existante de cette colonne pour l'enregistrement. Je peux accéder au menu déroulant dans l'événement ItemDataBound. Voici le code:
protected void listViewABC_ItemDataBound(object sender, ListViewItemEventArgs e)
{
// This stmt is used to execute the code only in case of edit
if (((ListView)(sender)).EditIndex != -1 && ((ListViewDataItem)(e.Item)).DisplayIndex == ((ListView)(sender)).EditIndex)
{
((DropDownList)(e.Item.FindControl("ddlXType"))).SelectedValue = ((MyClass)((ListViewDataItem)e.Item).DataItem).XTypeId.ToString();
((DropDownList)(e.Item.FindControl("ddlIType"))).SelectedValue = ((MyClass)((ListViewDataItem)e.Item).DataItem).ITypeId.ToString();
}
}
protected void grvSecondaryLocations_RowEditing(object sender, GridViewEditEventArgs e)
{
grvSecondaryLocations.EditIndex = e.NewEditIndex;
DropDownList ddlPbx = (DropDownList)(grvSecondaryLocations.Rows[grvSecondaryLocations.EditIndex].FindControl("ddlPBXTypeNS"));
if (ddlPbx != null)
{
ddlPbx.DataSource = _pbxTypes;
ddlPbx.DataBind();
}
.... (more stuff)
}
Le vérifié réponse de balexandre fonctionne très bien. Mais cela créera un problème s'il est adapté à d'autres situations.
Je l'ai utilisé pour modifier la valeur de deux contrôles d'étiquette - lblEditModifiedBy
et lblEditModifiedOn
- lorsque je modifiais une ligne, afin que les bons ModifiedBy et ModifiedOn
soient enregistrés dans le db sur 'Update'.
Lorsque j'ai cliqué sur le bouton "Mettre à jour", dans l'événement RowUpdating
, il a montré les nouvelles valeurs que j'ai entrées dans la liste OldValues
. J'avais besoin des vraies "anciennes valeurs" comme valeurs Original_ lors de la mise à jour de la base de données. (Il y a un ObjectDataSource
attaché au GridView
.)
Le correctif consiste à utiliser le code de balexandre, mais sous une forme modifiée dans le gv_DataBound
un événement:
protected void gv_DataBound(object sender, EventArgs e)
{
foreach (GridViewRow gvr in gv.Rows)
{
if (gvr.RowType == DataControlRowType.DataRow && (gvr.RowState & DataControlRowState.Edit) == DataControlRowState.Edit)
{
// Here you will get the Control you need like:
((Label)gvr.FindControl("lblEditModifiedBy")).Text = Page.User.Identity.Name;
((Label)gvr.FindControl("lblEditModifiedOn")).Text = DateTime.Now.ToString();
}
}
}
Vous pouvez utiliser SelectedValue:
<EditItemTemplate>
<asp:DropDownList ID="ddlPBXTypeNS"
runat="server"
Width="200px"
DataSourceID="YDS"
DataTextField="CaptionValue"
DataValueField="OID"
SelectedValue='<%# Bind("YourForeignKey") %>' />
<asp:YourDataSource ID="YDS" ...../>
</EditItemTemplate>