模板字段消失

Wes*_*s H 5 c# asp.net gridview webforms

我有一个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>
Run Code Online (Sandbox Code Playgroud)

代码背后

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();
Run Code Online (Sandbox Code Playgroud)

方法GridViewTools.CreateBoundField是一个自定义方法,它设置我的默认boundfield属性并返回BoundField对象.

public static BoundField CreateBoundField(...){...}
Run Code Online (Sandbox Code Playgroud)

在测试中,gridview根据需要填充初始加载.但是,单击按钮时,RowCommand事件不会触发,两个模板字段都会消失.然后下一个gridview.RowDataBound事件抛出一个空对象错误,因为在该行中找不到下拉列表.

如果我删除添加绑定字段[Columns.Insert]的行,则在单击btnSave并且模板字段保持不变时,RowCommand将按预期触发.如果我再次添加一个绑定字段列,则RowCommand不会触发,模板字段也会消失.

有什么建议?为什么向gridview添加新列会使预先存在的按钮的RowCommand事件无效并使模板字段消失?

更新 我从网格视图声明中删除了模板字段,并将控件添加到绑定字段,但仍然得到相同的结果.显示初始加载,但一旦点击就消失.

我还查看了Page_Unload事件中的网格视图,它仍然包含该点的列,即使它们没有显示在屏幕上.在Page_Unload之后我可以捕获任何事件吗?

dpa*_*ant 2

在代码后面构建所有内容。这不是一个偏好问题。请阅读动态 Web 服务器控件和视图状态

网页表格:

<asp:GridView ID="gvDetails" runat="server"
    AutoGenerateColumns="false" 
    SkinID="gridviewGray" 
    CellPadding="3" 
    OnRowDataBound="OnRowDataBound"
    OnRowCommand="gvDetails_RowCommand"
    AllowSorting="true">
</asp:GridView>
Run Code Online (Sandbox Code Playgroud)

背后代码:

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)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)