开发者

Preserving CheckBox's Value in Dynamic GridView TemplateField

开发者 https://www.devze.com 2023-04-01 05:21 出处:网络
I am trying to create a GridView which will contain a list of users and permission levels that they have access to. Each row will have the following fields: User_ID, Username, Permission1, Permission2

I am trying to create a GridView which will contain a list of users and permission levels that they have access to. Each row will have the following fields: User_ID, Username, Permission1, Permission2, ..., PermissionN, where the values of permissions field are "0" if the user does not have that permission and "1" if they do (note that columns returned by the DAL are not named Permission1, but rather are the actual name of the permission). I would like to represent the data by using CheckBoxes, to allow an admin to quickly grant or revoke permissions to a large number of users at once.

Since I will not know the number of permissions before-hand, I dynamically create TemplateFields and CheckBoxes, and this works fine; the GridView shows the current permission levels of all the users. I run into a problem when I try to update permissions based on the user checking and unchecking boxes.

Once the user is done changing permissions, I have an "Update" button, which of course causes a postback. Since the postback occurs before the OnClick event, by the time I reach OnClick all of the CheckBoxes have been reset to their initial values. Is there a way I can somehow grab the value of the CheckBoxes' Checked property before the postback occurs? Is there another (better) way of doing this? Thanks.

ASPX:

<asp:GridView ID="gvUsers" runat="server" AutoGenerateColumns="False"
EnableModelValidation="True" DataKeyNames="ID">
</asp:GridView>
<asp:ObjectDataSource ID="odsUsers" runat="server" SelectMethod="GET_USERS"
TypeName="oDAL">
</asp:ObjectDataSource>
<asp:Button ID="btnUpdate" runat="server" Text="Update Permissions" OnCli开发者_C百科ck="btnUpdate_OnClick"/>

Code Behind:

private static string[] excludeCols = { "ID", "Username" };
protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack) // Removing the IsPostBack check refreshes the GridView when the Update button is clicked
        bindGridViewWithHiddenID(gvUsers, ((DataView)odsUsers.Select()).Table, excludeCols);
}

public static bool bindGridViewWithHiddenID(GridView gv, DataTable dt, string[] excludeCols)
{
    gv.Columns.Clear();
    gv.DataBind();
    if (gv != null && dt != null && dt.Rows.Count > 0)
    {
        DataControlField newField;
        foreach (DataColumn column in dt.Columns)
        {
            if (excludeCols.Contains(column.ColumnName))
            {
                newField = new BoundField();
                ((BoundField)newField).DataField = column.ColumnName;
            }
            else
            {
                newField = new TemplateField();
                ((TemplateField)newField).ItemTemplate = new CustomTemplate(column.ColumnName);
            }
            newField.HeaderText = column.ColumnName;
            if (column.ColumnName == "ID" || column.ColumnName.EndsWith("_ID"))
                newField.Visible = false;
            gv.Columns.Add(newField);
        }

        gv.DataSource = dt;
        gv.DataBind();
        return true;
    }
    return false;

}

// By this time execution reaches here the CheckBoxes have already been reset
protected void btnUpdate_Click(object sender, EventArgs e)
{
    ...
}

CustomTemplate class:

public class CustomTemplate : ITemplate
{
private string binding;
private static int count = 0;
public CustomTemplate(string colNameBinding)
{
    binding = colNameBinding;
}

public void InstantiateIn(Control container)
{
    CheckBox chk = new CheckBox();
    chk.ID = "chk" + count++;
    chk.DataBinding += new EventHandler(this.chk_OnDataBinding);
    container.Controls.Add(chk);
}

public void chk_OnDataBinding(object sender, EventArgs e)
{
    CheckBox chk = (CheckBox)sender;
    GridViewRow namingContainer = (GridViewRow)chk.NamingContainer;
    DataRowView dataRow = (DataRowView)namingContainer.DataItem;

    if (dataRow[binding].ToString() == "1")
        chk.Checked = true;
    else
        chk.Checked = false;
}


This behavior is expected and is normal. It has to do with the Page Life cycle and tracking of ViewState on dynamically added controls. I recommend you read this article from Scott Mitchell, specially the section titled: View State and Dynamically Added Controls.


I tried adding the GridView binding to OnInit() but since the CheckBoxes aren't actually instantiated until the GridView is DataBound, and since DataBinding will revert the GridView back to its original state, I seem to be stuck again.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号