【问题标题】:Gridview binding clears unexpectedlyGridview 绑定意外清除
【发布时间】:2012-12-30 14:29:34
【问题描述】:

我的网格视图有问题。我已经搜索了很多解决方案,但找不到任何答案。我想我已经找到了问题,当我按下更新按钮时,gridview 不再绑定 - 这会导致空值。我认为在 RowEditing 上绑定就足够了。我还能在哪里绑定我的 gridview?

请参阅下面的标记:

    <asp:GridView ID="ProductGridView" runat="server" AllowPaging="True" AllowSorting="True"
    AutoGenerateColumns="False" DataKeyNames="Id" OnRowEditing="ProductGridView_RowEditing"
    OnRowCancelingEdit="ProductGridView_RowCancelingEdit" OnRowUpdating="ProductGridView_RowUpdating"
    OnRowDeleting="ProductGridView_RowDeleting" OnDataBound="ProductGridView_DataBound" OnRowDataBound="ProductGridView_RowDataBound">
    <Columns>
        <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" CausesValidation="false" />
        <asp:TemplateField HeaderText="Name" SortExpression="Name">
            <EditItemTemplate>
                <asp:TextBox ID="txtName" runat="server" Text='<%# Bind("Name") %>'></asp:TextBox>
            </EditItemTemplate>
            <ItemTemplate>
                <asp:Label ID="lblName" runat="server" Text='<%# Eval("Name") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Quantity" SortExpression="Quantity">
            <EditItemTemplate>
                <asp:TextBox ID="txtQuantity" runat="server" Text='<%# Bind("Quantity") %>'></asp:TextBox>
            </EditItemTemplate>
            <ItemTemplate>
                <asp:Label ID="lblQuantity" runat="server" Text='<%# Eval("Quantity") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Family" SortExpression="Family.Name">
            <EditItemTemplate>
                <asp:DropDownList ID="ddlFamily" runat="server" OnInit="ddlFamily_Init">
                </asp:DropDownList>
            </EditItemTemplate>
            <ItemTemplate>
                <asp:Label ID="lblFamily" runat="server" Text='<%# Eval("Family.Name") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

还有代码隐藏:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            BindGridView(_productRepo.GetAll());
        }
    }

    private void BindGridView(object source)
    {
        ProductGridView.DataSource = source;
        ProductGridView.DataBind();
    }

    protected void ProductGridView_RowEditing(object sender, GridViewEditEventArgs e)
    {
        ProductGridView.EditIndex = e.NewEditIndex;
        BindGridView(_productRepo.GetAll()); // GetAll returns an IEnumerable.
        rowCount = ProductGridView.Rows.Count; // Count is 6 here, which is correct.
    }

    protected void ProductGridView_RowUpdating(object sender, GridViewUpdateEventArgs e)
    {
        rowCount = ProductGridView.Rows.Count; // Count is 0 here.
        //BindGridView(_productRepo.GetAll()); // Tried to rebind which works but getting the old values obviously. 
        //rowCount = ProductGridView.Rows.Count; // Count is 6 here.

        // Get the controls - all is null. Works ok when I use BindGridView above.
        TextBox txtName = FindChildControl<TextBox>(this.Page, "txtName");
        TextBox txtQuantity = FindChildControl<TextBox>(this.Page, "txtQuantity");
        DropDownList ddlFamily = FindChildControl<DropDownList>(this.Page, "ddlFamily");

        // More code to populate a new product and bind the gridview again etc.
    }

我还有一个 RowDataBound 方法。这会导致问题吗?

protected void ProductGridView_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.DataRow && (e.Row.RowState & DataControlRowState.Edit) == DataControlRowState.Edit)
        {
            DropDownList ddl = (DropDownList)e.Row.FindControl("ddlFamily");
            ddl.DataSource = _familyRepo.GetAll().Select(f => f.Name);
            ddl.DataBind();
            Product product = _productRepo.FindSingle(p => p.Id == (int)ProductGridView.DataKeys[e.Row.RowIndex].Value);
            ddl.SelectedIndex = (int)product.FamilyID - 1;
        }
    }

【问题讨论】:

    标签: c# asp.net data-binding gridview


    【解决方案1】:

    如果我理解正确,您是说数据网格中的表单控件在回发后消失或重置为初始状态。

    发生这种情况的原因是您在 Page_Load 方法中绑定了您的网格,这在页面生命周期中来得太晚,无法恢复控件值。在触发 LoadViewstate 和 LoadPostbackData 事件之后,您的网格才会加载,因此,每次进行回发时,您的网格控件都会以原始状态加载。

    我猜你对 asp.net 生命周期很熟悉,但如果不是,这里有一篇文章:http://msdn.microsoft.com/en-us/library/ms972976.aspx。我已经多次处理过这个问题,我花了一段时间才完全理解这里发生了什么。

    该问题的一个解决方案是在重写的 OnInit 方法中加载网格,该方法发生在恢复控制数据之前。像这样的东西应该可以工作:

    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        BindGridView(_productRepo.GetAll());
    }
    

    【讨论】:

    • 这很有帮助。行数现在是正确的值。但是,找不到我的控件。你有什么想法吗?
    • 看起来您正在使用 FindChildControl 方法查看整个页面以查找具有给定 ID 的控件。在 GridView 中查找控件时,您需要像在 ProductGridView_RowDataBound 中一样调用“e.Row.FindControl(controlName)”。
    • 我也试过TextBox txtName = (ProductGridView.Rows[e.RowIndex].FindControl("txtName") as TextBox); 没有结果。它也返回 null。
    • 我找到了问题所在。当我逐步执行 FindChildControl 方法时,它只会找到标签。因此,我认为当单击更新按钮时,EditItemTemplates 中的文本框会在我有机会搜索 gridview 之前返回到 ItemTemplates。我还没有找到解决办法。
    • 我刚刚测试了您的代码,并且能够通过使用 TextBox txtName = (TextBox)ProductGridView.Rows[e.RowIndex].FindControl("txtName"); 获得结果在 RowUpdating 方法中。您不应该将 FindChildControl 方法与 gridview 一起使用,因为每一行都有一个附加到控件 ID 的索引。例如,第一行 id 的文本框是“ProductGridView_txtName_0”。只有使用 GridViewRow 的 FindControl 才能获得正确的对象。
    【解决方案2】:

    我通常以这种方式进行数据绑定....试试这个函数并在你的页面加载和其他你需要的函数中调用它。

    protected void bind()
    {
        con.Open();
        SqlCommand cmd = new SqlCommand("Your Query", con);
        DataSet ds = new DataSet();
        SqlDataAdapter da = new SqlDataAdapter();
        da.SelectCommand = cmd;
    
        da.Fill(ds);
    
        gvCourse.DataSource = ds;
        gvCourse.DataBind();
    
        con.Close();
    
    }
    

    【讨论】:

    • 感谢您的回答。但是,绑定本身的代码不是问题。我需要帮助的是如何以及何时调用绑定。
    • 您应该在对网格进行更改(如编辑、更新和插入)时调用绑定函数,如果需要,也可以在页面加载中调用。您可以像调用一样调用绑定函数任何其他功能,按其名称。因此,在您的程序中,您应该在行编辑功能、行更新和页面加载结束时调用绑定功能。希望这会有所帮助:-)
    【解决方案3】:

    或者您可以简单地将 !Page.IsPostBack 替换为 !IsPostBack

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            BindGridView(_productRepo.GetAll());
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-03
      • 1970-01-01
      • 2011-01-16
      相关资源
      最近更新 更多