demoshop

demo, trying to be the best_

昨天 demo 寫了一篇【實作 GridView 整列選取功能使用 JavaScript】的文,今天要再來介紹一下如何使用 C# 的方法來實作 GridView 整列選取的功能,雖然說是使用 C# 但是還是有很多是寫 JavaScript 的,畢竟這本來就是 JavaScript 做的事情。

demo廢言前面的步驟和上一篇一樣

 

●首先頁面上拉出一個 GridView 並且加上 onload 的事件

<asp:GridView ID="GridView1" runat="server" onload="GridView1_Load">
</asp:GridView>

●而程式中就直接給資料

protected void GridView1_Load(object sender, EventArgs e)
{
List<int> fakeData = new List<int>();
fakeData.AddRange(Enumerable.Range(1, 10));
this.GridView1.DataSource = fakeData;
this.GridView1.DataBind();
}

●這時候執行來看就可以看到以下的畫面了


●接下來要確定選擇是有用的所以再加一個 onselectedindexchanged 事件

<asp:GridView ID="GridView1" runat="server"
onload="GridView1_Load"
EnableModelValidation="True"
onselectedindexchanged="GridView1_SelectedIndexChanged">
</asp:GridView>

●程式就來寫

protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
Response.Write("您選取了:"+ ((GridView)sender).SelectedIndex);
}

●再來因為我們要加上 選取的事件所以要再幫 GridView 增加一個 RowDataBound 事件

<asp:GridView ID="GridView1" runat="server"
    onload="GridView1_Load"
    EnableModelValidation="True"
    onselectedindexchanged="GridView1_SelectedIndexChanged"
    onrowdatabound="GridView1_RowDataBound">
</asp:GridView>

●後端的程式這樣寫

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        e.Row.Attributes["onclick"] =
        this.Page.ClientScript.GetPostBackEventReference((GridView)sender, "Select$" + e.Row.RowIndex);
    }
    #region 為了避免有控制項的 Cell 點選後會冒泡到整列選的事件
    foreach (TableCell item in e.Row.Cells)
    {
        if (item.HasControls())
        {
            item.Attributes["onclick"] = "event.cancelBubble=true;";
        }
    }
    #endregion
}

注意事項我們手動加上了 Select 命令使用的 Postback Script 並且為了排除 JavaScript 的事件冒泡所以用了一個很大膽的判斷,只要欄位內包含控制項就加上 event.cancelBubble=true;


●這個時候執行頁面,會發現的確可以點了,但是點下去以後會出現這個錯誤

無效的回傳或回呼引數。已在組態中使用 <pages enableEventValidation="true"/> 或在網頁中使用 <%@ Page EnableEventValidation="true" %> 啟用事件驗證。基於安全性理由,這項功能驗證回傳或回呼引數是來自原本呈現它們的伺服器控制項。如果資料為有效並且是必需的,請使用 ClientScriptManager.RegisterForEventValidation 方法註冊回傳或回呼資料,以進行驗證。


●為了解決這錯誤,需要讓 ASP.NET 認識它,因此在後端加上一個方法來註冊進去吧

protected override void Render(HtmlTextWriter writer)
{
    for (int i = 0; i < this.GridView1.Rows.Count; i++)
    {
        Page.ClientScript.RegisterForEventValidation(this.GridView1.UniqueID, "Select$" + i.ToString());
    }
    base.Render(writer);
}

注意事項對於此錯誤出現的原因建議可以參考黑暗大的文章,有詳細的說明【按我觀看


demo廢言再執行頁面後,點選 GridVIew 就不會再出現錯誤了,以上的寫法一樣有幾點需要注意的

  1. 範例中在RowDataBound只有判斷當有控制項的時候就防止冒泡的寫法會造成你的整列點選功能變得很殘,怎麼說呢,因為所有的控制項包含太廣,我們應該只能限制需要點的比如說 RedioButton 或 CheckBox 這類需要使用者點的,對於 Label 這種只是看的就應該還讓他點選,這部份是需要調整的部份,還請使用者自行撰寫,最後您可以將範例的 GridView 增加一個新的資料行再將它轉成樣板,就會發現新增的那行無法點囉。
<asp:GridView ID="GridView1" runat="server"
    onload="GridView1_Load"
    EnableModelValidation="True"
    onselectedindexchanged="GridView1_SelectedIndexChanged"
    onrowdatabound="GridView1_RowDataBound">
    <Columns>
        <asp:TemplateField HeaderText="不能點">
            <ItemTemplate>
                <asp:Label ID="Label1" runat="server" Text="我不能點"></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

 

 

回應討論