2012-07-10 59 views
2

這可能看起來像重複,但我不這麼認爲。我已經搜索了stackoverflow,可能還不夠。GridView的OnRowCommand第一次沒有開通

這裏是我的挑戰:

<asp:LinkButton runat="server" ID="DeleteRow" CommandName="deleterow" 
    CommandArgument='<%# Eval("ID") %>' Text="Delete" 
    OnClientClick="return confirm('Are you sure you want to delete this record?');" /> 

如果您單擊鏈接的第一次,OnRowCommand不會被解僱。當你第二次點擊它時,它會起作用。

我看着源頭,我有這些差異。

//When you first load the page: the GUID is the PK for that row 
1. javascript:__doPostBack('ctl00$content$gvSchoolClasses$58fd1759-f358-442e-bf73-2e9cedfc27e8$DeleteRow','') 

//After the link was clicked the first time, the link changed and the ID empty, but works 
2. javascript:__doPostBack('ctl00$content$gvSchoolClasses$ctl02$DeleteRow','') 

我複製從asp:LinkButtonhref兩個代碼之前和後,點擊。

出了什麼問題?我的頁面RowDataBound上只有一個其他事件。

protected void gvSchoolClasses_RowDataBound(object sender, GridViewRowEventArgs e) 
    { 
     e.Row.ID = Guid.NewGuid().ToString(); 
    } 

    protected void Page_Load(object sender, EventArgs e) 
    { 
     CheckAuthentication(); 

     if (!Page.IsPostBack) 
     { 
      ClassesAcademicYearLabel.Text = "- Year " + Setting.Year; 
      //FillClassesList(); //filling some combo boxes. Have checked the codes here too 
      //FillLettersList(); //they didn't affect the Grid 
      FillGrid(); 
     } 

     ClassErrorLabel.Visible = false; 

    } 
+0

介意分享你的'RowDataBound'事件處理代碼?我很好奇你爲什麼排除它作爲問題來源 – 2012-07-10 19:27:05

+0

我相信裏面的代碼不應該影響linkBut​​ton。那影響了網格 – codingbiz 2012-07-10 19:30:20

+0

哪裏調用了'gvSchoolClasses.DataBind()'? 'Page_Load'? – 2012-07-10 19:32:58

回答

3

通過設置行的ID屬性在RowDataBound情況下,你已經創建你觀察問題。

由於RowDataBound事件直到頁面的控件已被添加到集合後才被觸發,ASP.NET無法更新已經計算的客戶端引用。因此,該命令不會以您期望的方式被解僱。

我注意到您已經將CommandArgument屬性設置爲RowDataBound事件中生成的ID,這也可能是您問題的一部分(取決於事件觸發的順序;我沒有管道圖表便利)。

編輯:這可以簡單地設置ClientID屬性(對不起,不是確切的名稱,但intellisense應該讓你的方式的其餘部分)到某種手動,而不是自動確定。這樣,您設置的ID永遠不會被框架更改。

更詳細地說明爲什麼你會看到這個問題了一下,考慮客戶端ID的呈現:

ctl00$content$gvSchoolClasses$ctl02$DeleteRow

此ID通過採取保證是(本頁)獨特聲明ID(DeleteRow),並連續向上走控制層次結構並將父ID預先添加到字符串中。 JS代碼可以確信,將該字符串傳遞給getElementById的行爲將以一致的,可預測的方式進行。

爲了能夠生成所述ID,層次結構中的所有控件必須已經存在並由渲染引擎進行計算。

現在讓我們考慮一下當控件的ID屬性發生變化時(注意,這不是ClientID,而只是名稱爲ID的屬性)會發生什麼情況。

ctl00$content$gvSchoolClasses$58fd1759-f358-442e-bf73-2e9cedfc27e8$DeleteRow

你會注意到,而不是該行的命名容器(cl02),它現在有你生成並分配給它的GUID。嘗試使用先前分配的ID訪問此容器的客戶端JS將會失望,因爲它將不再按預期工作!

當ASP.NET控件通過調用觸發回發到javascript:__doPostBack('ctl00$content$gvSchoolClasses$58fd1759-f358-442e-bf73-2e9cedfc27e8$DeleteRow','')

回傳將會發生很好,很正常,但(你可以通過檢查回發的形式PARAMS驗證這一點)當服務器處理請求時,它將嘗試從視圖狀態中補充一個不存在的控件。因此,它將創建一個新的控件實例(使用正確的ID),它不知道命令已經發出,所以事件(s)永遠不會被觸發。由於沒有發生數據綁定(這是回發,並且您的代碼正確檢查該情況),因此ID永遠不會重置,並且該命令可以正常觸發

+0

從RowDataBound工作中刪除e.Row.ID。我認爲解釋是引入的'Guid.NewGuid'與postback方法中預期的字符串混淆了。謝謝。 – codingbiz 2012-07-10 20:03:43

+0

感謝您的解釋。我想要這個,但我覺得我會谷歌它。 – codingbiz 2012-07-10 20:11:59

+0

明智和完美的解釋 – codingbiz 2012-07-10 22:04:55

0

您需要將行索引設置爲CommandArgument鏈接按鈕不是GUID

正如你說的第二次合作,但如下圖所示

//After the link was clicked the first time, the link changed and the ID empty, but works 
2. javascript:__doPostBack('ctl00$content$gvSchoolClasses$ctl02$DeleteRow','') 
1

的HTML不要在您的RowDataBound事件改變Row.ID。要麼在網格中更改不同的值,要麼在gridview標記中執行此操作:

CommandArgument ='<%:Guid.NewGuid.ToString(); %>」

如果你想做到這一點在後面的代碼,你可以做這樣的事情:

protected void gv_RowDataBound(object sender, GridViewRowEventArgs e) 
     { 
      LinkButton deleteRow = (LinkButton)e.Row.FindControl("DeleteRow"); 
      if (deleteRow != null) 
       deleteRow.CommandArgument = Guid.NewGuid().ToString(); 
     } 
+0

這是一段代碼行編輯我留下未使用,我改變了你剛纔的建議'<%:Guid.NewGuid.ToString(); %>'。所以現在是多餘的現在造成了麻煩。謝謝。 – codingbiz 2012-07-10 20:09:32

相關問題