2010-08-04 72 views
0

我有一個嵌套的GridView放置在ListView中。 GridView呈現完全適用於綁定在其數據源中的所有實體。嵌套的GridView不會觸發行事件

我的gridview中的每條記錄都有兩個按鈕 - 「刪除」和「編輯」。我遇到的問題是連接到每個按鈕的方法都不會被觸發。

我認爲這種行爲的原因是因爲我的ListView的數據綁定只發生在第一頁加載,而不是每一個後續的回發。因此,當發生回發時,嵌套的gridview事件再也不會被連接 - 因此我的方法不會被解僱。

這裏是我的代碼[簡化]是這樣的:

<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> 

代碼背後:

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'); 
} 

我試圖修改上面的代碼,並刪除 「的IsPostBack!」 條款,以及事件實際上當點擊GridView中的一個按鈕時被觸發。不過,我覺得每回發一次數據綁定感覺不舒服,認爲應該有比這更好的解決方案。

回答

1

我解決了這個問題,但從未更新過這篇文章。因此,對於任何感興趣的人來說,問題在於 - 按鈕事件的佈線需要在事件處理程序的RowCreated中完成,而不是RowCommand事件處理程序。

這是爲什麼?看看什麼MSDN不得不說每個兩個事件:

GridView.OnRowCreated方法:

之前GridView控件可以呈現, 一個GridViewRow對象必須創建 對於控件中的每一行。當GridView控件中的每個 行都創建爲 時,引發RowCreated事件 。這使您可以提供 事件處理方法,該方法執行 自定義例程,例如,在發生此事件時,將 自定義內容添加到行中。

GridView。OnRowDataBound方法:

GridView控件可以呈現之前, 在控制各行必須綁定 到數據源的記錄。 RowDataBound事件在 數據行(由GridViewRow 對象表示)綁定到GridView控件的 中的數據時引發。這使您能夠提供事件處理方法, 執行自定義例程,例如 修改數據綁定 到該行的值,無論何時發生此事件 。

現在究竟是不是從MSDN寫了明確的是:當由兩個不同的來源

  1. 從數據源創建的行

    OnRowCreated被觸發 - 獲取傳遞當的DataBind調用

  2. 從視圖狀態 - 在回發,行從視圖狀態加載,而不是從數據源

因此,當發生回發時,我們需要在每一行再次綁定按鈕事件。但是,因爲我們在RowCommand中執行事件的連線,所以這些方法永遠不會再被調用 - 因爲它們只會在DataBind上被觸發。我們需要做的是將RowCreated方法中的按鈕連接起來,這將在我們首次將數據綁定到GridView時調用,並在每次回發時從GridView的ViewState創建行時調用。

2

我知道這篇文章很舊,但是很晚才發現我的項目正在進行中。我不是專家,但我相信問題在於在Postback中設置了ItemDataBound事件。 Databind()可以保留在Postback語句中,但設置事件需要在外部。在回發時,ItemDataBound事件不再存在,因此GridView事件由於包含在ListView的ItemDataBound事件中而不存在。所以

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

應該閱讀....

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

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

當代碼對控件設置事件背後通常最好是始終設置他們Posback聲明之外。當它們在aspx頁面上設置時,它將永遠存在並不重要。