0

グリッドビューに問題があります。解決策をたくさん検索しましたが、答えが見つかりません。更新ボタンを押すとグリッドビューがバインドされなくなり、null 値になるという問題が発生したと思います。RowEditing でバインドするだけで十分だと思いました。グリッドビューを他にどこにバインドできますか?

以下のマークアップを参照してください。

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

3 に答える 3

0

私があなたを正しく理解している場合、あなたはデータグリッド内のフォームコントロールが消えるか、ポストバック後に初期状態にリセットされると言っています。

これが発生する理由は、Page_Loadメソッドでグリッドをバインドしているためです。これは、ページのライフサイクルの後半で制御値を復元するには遅すぎます。LoadViewstateイベントとLoadPostbackDataイベントが発生するまでグリッドは読み込まれないため、ポストバックが行われるたびにグリッドのコントロールが元の状態で読み込まれます。

あなたはasp.netのライフサイクルに精通していると思いますが、そうでない場合は、http://msdn.microsoft.com/en-us/library/ms972976.aspxの記事を参照してください。私はこの問題に何度も取り組んできましたが、ここで何が起こっているのかを完全に理解するのにしばらく時間がかかりました。

この問題の解決策の1つは、オーバーライドされたOnInitメソッドでグリッドをロードすることです。これは、制御データが復元される前に発生します。このようなものが機能するはずです:

protected override void OnInit(EventArgs e)
{
    base.OnInit(e);
    BindGridView(_productRepo.GetAll());
}
于 2012-12-30T14:47:57.737 に答える
0

または、単に !Page.IsPostBack を !IsPostBack に置き換えることができます

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        BindGridView(_productRepo.GetAll());
    }
}
于 2012-12-31T16:38:50.307 に答える
0

私は通常、この方法でデータバインディングを行います....この関数を試して、ページの読み込みや必要な他の関数で呼び出します。

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();

}
于 2012-12-30T14:58:03.510 に答える