1

我正在尝试创建一个 GridView ,其中将包含他们有权访问的用户列表和权限级别。每行将包含以下字段:User_ID、用户名、Permission1、Permission2、...、PermissionN,如果用户没有该权限,则权限字段的值为“0”,如果有,则为“1”(注意DAL 返回的列未命名为 Permission1,而是权限的实际名称)。我想使用 CheckBoxes 来表示数据,以允许管理员一次快速授予或撤销大量用户的权限。

由于我事先不知道权限的数量,所以我动态创建了 TemplateFields 和 CheckBoxes,这很好用;GridView 显示所有用户的当前权限级别。当我尝试根据用户选中和取消选中框更新权限时遇到问题。

一旦用户完成更改权限,我就有一个“更新”按钮,这当然会导致回发。由于回发发生在 OnClick 事件之前,当我到达 OnClick 时,所有 CheckBox 都已重置为其初始值。有没有办法在回发发生之前以某种方式获取 CheckBoxes 的 Checked 属性的值?还有另一种(更好的)方法吗?谢谢。

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" OnClick="btnUpdate_OnClick"/>

代码背后:

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)
{
    ...
}

自定义模板类:

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;
}
4

2 回答 2

0

这种行为是预期的并且是正常的。它与页面生命周期和动态添加控件上的 ViewState 跟踪有关。我建议您阅读Scott Mitchell 的这篇文章,特别是标题为:视图状态和动态添加的控件的部分。

于 2011-09-02T01:13:11.870 回答
0

我尝试将 GridView 绑定添加到 OnInit() 但由于在 GridView 为 DataBound 之前实际上并未实例化 CheckBox,并且由于 DataBinding 会将 GridView 恢复为其原始状态,因此我似乎又被卡住了。

于 2011-09-02T03:28:04.250 回答