我正在尝试创建一个GridView,它将包含他们有权访问的用户和权限级别列表。每行将包含以下字段:User_ID,Username,Permission1,Permission2,...,PermissionN,其中如果用户没有该权限,则权限字段的值为“0”,如果用户没有,则为“1”(注意, DAL返回的列不是Permission1,而是权限的实际名称。我想通过使用CheckBox来表示数据,以允许管理员一次快速授予或撤销对大量用户的权限。
由于我不知道之前的权限数量,我动态创建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)
{
...
}
CustomTemplate类:
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;
}
答案 0 :(得分:0)
此行为是预期的并且是正常的。它与页面生命周期和动态添加控件上的ViewState跟踪有关。我建议你阅读Scott Mitchell的this article,特别是标题为:查看状态和动态添加控件的部分。
答案 1 :(得分:0)
我尝试将GridView绑定添加到OnInit(),但由于CheckBox实际上没有实例化,直到GridView是DataBound,并且由于DataBinding将GridView恢复到其原始状态,我似乎再次陷入困境。