2010-08-04 10 views
0

J'ai un GridView imbriqué qui est placé dans un ListView. Le GridView rend parfaitement bien avec toutes les entités qui sont liées à l'intérieur de sa source de données.Evénements de ligne imbriqués GridView

Chaque enregistrement dans ma grille a deux boutons - 'supprimer' et 'éditer'. Le problème que j'ai est que les méthodes câblées à chacun de ces boutons ne sont jamais virées.

Je pense que la raison de ce comportement est que ma liaison de données ListView se produit uniquement sur le premier chargement de page, et non sur chaque publication ultérieure. Par conséquent, lorsqu'une publication se produit, les événements de la grille imbriquée ne sont jamais câblés à nouveau, ce qui explique pourquoi mes méthodes ne sont pas déclenchées.

Voici ce que mon code [simplifié] ressemble:

<asp:ListView ID="uiListView" ... runat="server"> 
    <LayoutTemplate> 
     ... 
    </LayoutTemplate> 
    <ItemTemplate> 
     ... 
     <asp:GridView ID="uiGridView" 
        OnRowDataBound="uiGridView_RowDataBound" 
        OnRowEditing="uiGridView_RowEditing" 
        OnRowDeleting="uiGridView_RowDeleting" runat="server"> 
      <Columns> 
       ... 
       <asp:TemplateField> 
        <ItemTemplate> 
         <asp:Button ID="uiEditRowButton" CausesValidation="false" CommandName="Edit" Text="Edit" runat="server" /> 
         <asp:Button ID="uiRemoveRowButton" CausesValidation="false" CommandName="Delete" Text="Remove" runat="server" /> 
        </ItemTemplate> 
       </asp:TemplateField> 
      </Columns> 
     </asp:GridView> 
     ... 
    </ItemTemplate> 
</asp:ListView> 

code Derrière:

protected void Page_Load(object sender, EventArgs e) 
{ 
    if (!IsPostBack) { 
     uiListView.ItemDataBound += new EventHandler<ListViewItemEventArgs>(uiListView_ItemDataBound); 
     uiListView.DataSource = ...; 
     uiListView.DataBind(); 
    } 
} 

// Find a GridView and bind relevant data to it 
private void uiListView_ItemDataBound(object sender, ListViewItemEventArgs e) 
{ 
    if (e.Item.ItemType == ListViewItemType.DataItem) { 
     ListViewDataItem listViewDataItem = (ListViewDataItem) e.Item; 

     GridView uiGridView = (GridView)listViewDataItem.FindControl("uiGridView"); 
     ... 
     uiGridView.DataSource = ...; 
     uiGridView.DataBind(); 
    } 
} 

// For every row being bound to GridView, register the edit and delete 
// buttons as postback controls 
protected void uiGridView_RowDataBound(object sender, GridViewRowEventArgs e) 
{ 
    if (e.Row.RowType == DataControlRowType.DataRow) 
    { 
     Control uiEditButton = e.Row.FindControl("uiEditRowButton"); 
     if (uiEditButton != null) { 
      ScriptManager.GetCurrent(Page).RegisterAsyncPostBackControl(uiEditButton); 
     } 

     Control uiRemoveRowButton = e.Row.FindControl("uiRemoveRowButton"); 
     if (uiRemoveRowButton != null) { 
      ScriptManager.GetCurrent(Page).RegisterAsyncPostBackControl(uiRemoveRowButton); 
     } 
    } 
} 

// Method runs when a GridView's edit button is clicked 
protected void uiGridView_RowEditing(object sender, GridViewEditEventArgs e) 
{ 
    Console.WriteLine('Editing Row...'); 
} 

// Method runs when a GridView's delete button is clicked 
protected void uiGridView_RowDeleting(object sender, GridViewDeleteEventArgs e) 
{ 
    Console.WriteLine('Deleting Row'); 
} 

J'ai essayé de modifier le code ci-dessus et en supprimant la clause "IsPostBack!", Et les événements effectivement été viré quand un bouton dans le GridView a été cliqué. Cependant, je ne me sens pas à l'aise de faire une base de données sur chaque publication et pense qu'il devrait y avoir une meilleure solution que cela.

Répondre

1

J'ai résolu ce problème mais je n'ai jamais mis à jour ce post. Donc, pour toute personne intéressée, voici le problème: le câblage des événements de bouton doit être effectué dans le gestionnaire d'événements RowCreated et non dans le gestionnaire d'événements RowCommand.

Pourquoi est-ce? Jetez un oeil à ce que MSDN a à dire pour chacun des deux événements:

GridView.OnRowCreated Méthode:

Avant le contrôle GridView peut être rendu, un objet GridViewRow doit être créé pour chaque ligne du contrôle. L'événement RowCreated est déclenché lorsque chaque ligne dans le contrôle GridView est créée . Cela vous permet de fournir une méthode de gestion d'événements qui exécute une routine personnalisée, telle que l'ajout de contenu personnalisé à une ligne, chaque fois que cet événement se produit.

GridView.OnRowDataBound Méthode:

avant que le contrôle GridView peut être rendu, chaque ligne de la commande doit être lié à un enregistrement dans la source de données. L'événement RowDataBound est déclenché lorsqu'une ligne de données (représentée par un objet GridViewRow ) est liée à des données dans le contrôle GridView . Cela vous permet de fournir une méthode de gestion d'événements qui effectue une routine personnalisée, telle que en modifiant les valeurs des données liées à la ligne, chaque fois que cet événement se produit.

Maintenant, ce qui ne ressort pas de l'écriture jusqu'à msdn est la suivante:

OnRowCreated est déclenchée lorsqu'une ligne est créée par deux sources différentes

  1. De la DataSource - qui est passé lorsque DataBind est invoqué
  2. de l'ViewState - sur postback, les lignes sont chargées à partir du ViewState et non à partir des sources de données

Par conséquent, quand une publication se produit, nous devons relier les événements de bouton sur chaque ligne. Toutefois, étant donné que nous effectuons le câblage des événements dans RowCommand, ces méthodes ne sont jamais appelées à nouveau, car elles ne sont déclenchées que sur DataBind. Ce que nous devons faire à la place est de câbler les boutons à l'intérieur de la méthode RowCreated, qui sera appelée lorsque nous donnons des données DataBind à la GridView, et à chaque publication lorsque des lignes sont créées à partir de ViewState de GridView.

2

Je sais que cet article est ancien, mais j'ai travaillé très tard sur mon projet. Je ne suis pas un expert, mais je crois que les problèmes résident dans le fait que l'événement ItemDataBound soit défini dans le! Postback. Le Databind() peut rester dans l'instruction Postback mais définir l'événement doit être à l'extérieur. Lors de la publication, l'événement ItemDataBound n'existe plus et, par conséquent, les événements gridview n'existent pas depuis son contenu dans l'événement ItemDataBound de la liste. Alors

if (!IsPostBack) { 
    uiListView.ItemDataBound += new EventHandler<ListViewItemEventArgs>(uiListView_ItemDataBound); 
    uiListView.DataSource = ...; 
    uiListView.DataBind(); 
} 

devrait lire ....

uiListView.ItemDataBound += new EventHandler<ListViewItemEventArgs>(uiListView_ItemDataBound); 

if (!IsPostBack) {   
    uiListView.DataSource = ...; 
    uiListView.DataBind(); 
} 

Lors de la configuration des événements sur les contrôles dans le code derrière il est normalement préférable de les mettre toujours en dehors de la déclaration Posback. Lorsque vous les définissez sur la page aspx, cela n'aura aucune importance, car il existera toujours.