我有一个gridview,用于根据下拉列表中的选定值显示记录。
在gridview中,后面的代码中添加了动态数量的绑定字段列,然后是模板字段中的下拉列表和第二个模板字段中的按钮。
问题是,当我点击按钮时,模板字段会消失。
网格视图
<asp:UpdatePanel ID="upnlDetail" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:GridView ID="gvDetails" runat="server"
AutoGenerateColumns="false"
SkinID="gridviewGray"
CellPadding="3"
OnRowCommand="gvDetails_RowCommand"
OnRowDataBound="gvDetails_RowDataBound"
AllowSorting="true">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:DropDownList ID="ddlStatus" runat="server"
AutoPostBack="true"
OnSelectedIndexChanged="ddlStatus_SelectedIndexChanged">
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="btnSave" runat="server"
CommandName="Save"
CommandArgument="<%# ((GridViewRow) Container).RowIndex %>"
Text="Save" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
代码背后
while (gvDetails.Columns.Count > 2) //Don't remove the rightmost columns
{
gvDetails.Columns.RemoveAt(0);
}
gvDetails.Columns.Insert(0, GridViewTools.CreateBoundField(
"Request.Amount", "Amount", "Money", 50));
gvDetails.Columns.Insert(0, GridViewTools.CreateBoundField(
"Request.CustomerName", "Customer", "comment", 200));
gvDetails.Columns.Insert(0, GridViewTools.CreateBoundField(
"Request.BillAccountFormatted", "Account", "text", 100));
gvDetails.Columns.Insert(0, GridViewTools.CreateBoundField(
"Request.Id", "Request", "int", 50));
gvDetails.DataSource = dt;
gvDetails.DataBind();
方法GridViewTools.CreateBoundField是一个自定义方法,用于设置我的默认boundfield属性并返回BoundField对象。
public static BoundField CreateBoundField(...){...}
在测试中,gridview根据需要填充初始加载。但是,单击按钮时,RowCommand事件不会触发,两个模板字段都会消失。然后下一个gridview.RowDataBound事件抛出一个空对象错误,因为在该行中找不到下拉列表。
如果删除添加绑定字段[Columns.Insert]的行,则在单击btnSave并且模板字段保持不变时,RowCommand将按预期触发。如果我再次添加一个绑定字段列,则RowCommand不会触发,模板字段也会消失。
有什么建议吗?为什么向gridview添加新列会使预先存在的按钮的RowCommand事件无效并使模板字段消失?
更新 我已经从网格视图声明中删除了模板字段,并将控件添加到绑定字段,但仍然得到相同的结果。显示初始加载,但一旦点击就消失。
我还查看了Page_Unload事件中的网格视图,它仍然包含该点的列,即使它们没有显示在屏幕上。在Page_Unload之后是否可以捕获任何事件?
答案 0 :(得分:1)
这很有趣。它似乎只在BoundFields被插入时才会发生。将BoundFields添加到Grid的末尾时,它确实有效。
gvDetails.Columns.Add(GridViewTools.CreateBoundField("Request.Amount", "Amount", "Money", 50));
但是你可能想在GridView的末尾使用DropDown和Button。所以你也可以创建那些动态,而不是仅仅向DropDownList添加数据。 所以要做的第一件事是添加2个额外的虚拟BoundField列来保存Button和DropDownList。
gvDetails.Columns.Add(GridViewTools.CreateBoundField("", "DropDownList", "int", 50));
gvDetails.Columns.Add(GridViewTools.CreateBoundField("", "Button", "int", 50));
现在更改RowDataBound事件以添加控件。
protected void gvDetails_RowDataBound(object sender, GridViewRowEventArgs e)
{
//check if the row is a datarow
if (e.Row.RowType == DataControlRowType.DataRow)
{
//create a dropdownlist and add some data
DropDownList ddl = new DropDownList();
ddl.ID = "ddlStatus";
ddl.Items.Add(new ListItem() { Text = "Option 1", Value = "1" });
ddl.Items.Add(new ListItem() { Text = "Option 2", Value = "2" });
ddl.Items.Add(new ListItem() { Text = "Option 3", Value = "3" });
//create a save button
Button btn = new Button();
btn.ID = "btnSave";
btn.CommandName = "save";
btn.Text = "Save";
btn.CommandArgument = e.Row.RowIndex.ToString();
//add the controls to the last 2 cells
e.Row.Cells[e.Row.Cells.Count - 2].Controls.Add(ddl);
e.Row.Cells[e.Row.Cells.Count - 1].Controls.Add(btn);
}
}
但要实现这一点,您需要将DataBind()
GridView放在IsPostBack
检查之外,但要在其中添加BoundFields。
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack == false)
{
//add the boundfields here
}
//bind gridview on every postback
gvDetails.DataSource = dt;
gvDetails.DataBind();
}
ASPX现在看起来像这样
<asp:GridView ID="gvDetails" runat="server" AutoGenerateColumns="false"
OnRowDataBound="gvDetails_RowDataBound" OnRowCommand="gvDetails_RowCommand"></asp:GridView>
好吧,你现在有一个完全动态创建的GridView。
答案 1 :(得分:1)
在代码中构建所有内容。这不是一个偏好的问题。请阅读Dynamic Web Server Controls and View State
web窗体:
<asp:GridView ID="gvDetails" runat="server"
AutoGenerateColumns="false"
SkinID="gridviewGray"
CellPadding="3"
OnRowDataBound="OnRowDataBound"
OnRowCommand="gvDetails_RowCommand"
AllowSorting="true">
</asp:GridView>
代码背后:
public class GridViewDropDownListTemplate : ITemplate
{
public void InstantiateIn(Control container)
{
DropDownList ddlStatus = new DropDownList();
ddlStatus.ID = "ddlStatus";
ddlStatus.Items.Add(new ListItem("Status 1"));
ddlStatus.Items.Add(new ListItem("Status 2"));
ddlStatus.Items.Add(new ListItem("Status 3"));
ddlStatus.Items.Add(new ListItem("Status 4"));
ddlStatus.AutoPostBack = true;
ddlStatus.SelectedIndexChanged += ddlStatus_SelectedIndexChanged;
container.Controls.Add(ddlStatus);
}
public void ddlStatus_SelectedIndexChanged(object sender, EventArgs e)
{
}
}
public class GridViewButtonTemplate : ITemplate
{
public void InstantiateIn(Control container)
{
Button btnSave = new Button();
btnSave.ID = "btnSave";
btnSave.Text = "Save";
container.Controls.Add(btnSave);
}
}
public partial class Default : System.Web.UI.Page
{
object[] data = new[]
{
new { Amount = 12500.00, Account = "1234-567-89" },
new { Amount = 87000.00, Account = "0000-999-88" }
};
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BuildBoundFields();
}
BuildTemplateFields();
BindData();
}
protected void BuildBoundFields()
{
// Amount bound field
BoundField boundFieldAmount = new BoundField();
boundFieldAmount.DataField = "Amount";
boundFieldAmount.HeaderText = "Amount";
boundFieldAmount.SortExpression = "Amount";
boundFieldAmount.ItemStyle.Width = Unit.Pixel(100);
gvDetails.Columns.Add(boundFieldAmount);
// Account bould field
BoundField boundFieldAccount = new BoundField();
boundFieldAccount.DataField = "Account";
boundFieldAccount.HeaderText = "Account";
boundFieldAccount.SortExpression = "Account";
boundFieldAccount.ItemStyle.Width = Unit.Pixel(250);
gvDetails.Columns.Add(boundFieldAccount);
// ...
}
protected void BuildTemplateFields()
{
// Status template field
TemplateField statusTemplateField = new TemplateField();
statusTemplateField.ItemTemplate = new GridViewDropDownListTemplate();
gvDetails.Columns.Add(statusTemplateField);
// Save template field
TemplateField saveTemplateField = new TemplateField();
saveTemplateField.ItemTemplate = new GridViewButtonTemplate();
gvDetails.Columns.Add(saveTemplateField);
}
protected void BindData()
{
gvDetails.DataSource = data;
gvDetails.DataBind();
}
protected void OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Button btnSave = (Button)e.Row.FindControl("btnSave");
if (btnSave != null)
{
btnSave.CommandArgument = e.Row.RowIndex.ToString();
}
}
}
protected void gvDetails_RowCommand(object sender, GridViewCommandEventArgs e)
{
}
}