ViewState中的DataTable返回已删除的行

时间:2016-02-18 22:35:50

标签: c# asp.net gridview datatable viewstate

我目前正在开发一个动态网格视图,允许用户添加或删除行,以便以后保存为数据库条目。

我的gridview标记是这样的:

<asp:UpdatePanel ID="upAirporterSchedule" runat="server" ChildrenAsTriggers="true" UpdateMode="Conditional">
                <ContentTemplate>
                    <asp:GridView ID="gvAirporterSchedule" runat="server" ShowFooter="true" AutoGenerateColumns="false" CssClass="table table-striped table-bordered table-hover dataTable no-footer" OnRowDataBound="gvAirporterSchedule_RowDataBound" OnRowCommand="gvAirporterSchedule_RowCommand">
                        <Columns>
                            <asp:TemplateField HeaderText="Location" ItemStyle-Width="25%">
                                <ItemTemplate>
                                    <asp:DropDownList ID="ddlScheduleLoc" runat="server" CssClass="form-control"></asp:DropDownList>
                                </ItemTemplate>
                            </asp:TemplateField>
                            <asp:TemplateField HeaderText="Start Date">
                                <ItemTemplate>
                                    <div class="input-group">
                                        <asp:TextBox ID="tbxAirporterStartDate" runat="server" CssClass="form-control date-picker" Text='<%# Eval("StartDateColumn") %>'></asp:TextBox>

                                        <span class="input-group-addon">
                                            <i class="fa fa-calendar"></i>
                                        </span>
                                    </div>
                                </ItemTemplate>
                            </asp:TemplateField>
                            <asp:TemplateField HeaderText="End Date">
                                <ItemTemplate>
                                    <div class="input-group">
                                        <asp:TextBox ID="tbxAirporterEndDate" runat="server" CssClass="form-control date-picker" Text='<%# Eval("EndDateColumn") %>'></asp:TextBox>

                                        <span class="input-group-addon">
                                            <i class="fa fa-calendar"></i>
                                        </span>
                                    </div>
                                </ItemTemplate>
                            </asp:TemplateField>
                            <asp:TemplateField HeaderText="Departure Time">
                                <ItemTemplate>
                                    <div class="input-group">
                                        <asp:TextBox ID="tbxAirporterDepTime" runat="server" CssClass="form-control time-picker" Text='<%# Eval("DeptTimeColumn") %>'></asp:TextBox>

                                        <span class="input-group-addon">
                                            <i class="fa fa-clock-o"></i>
                                        </span>
                                    </div>
                                </ItemTemplate>
                            </asp:TemplateField>
                            <asp:TemplateField HeaderText="Duration">
                                <ItemTemplate>
                                    <asp:TextBox ID="tbxAirporterDuration" runat="server" CssClass="form-control" Text='<%# Eval("DurationColumn") %>'></asp:TextBox>
                                </ItemTemplate>
                            </asp:TemplateField>
                            <asp:TemplateField HeaderText="Delete">
                                <ItemTemplate>
                                    <asp:Button ID="btnDel" runat="server" CssClass="btn btn-default" Text="Delete" CommandName="DeleteRow" />
                                </ItemTemplate>

                                <FooterStyle HorizontalAlign="Right" />
                                <FooterTemplate>
                                    <asp:Button ID="btnAdd" runat="server" CssClass="btn btn-default" Text="Add Entry" CommandName="AddRow" />
                                </FooterTemplate>
                            </asp:TemplateField>
                        </Columns>
                    </asp:GridView>
                </ContentTemplate>
            </asp:UpdatePanel>

除了这个网格,我在用户控件中还有其他一些字段。当我去保存时,用户将单击用户控件底部的按钮,该按钮将其上方的表单字段和网格打包到某些类中,然后将其发送到数据库代码以添加/更新此数据。 / p>

Page.Validate("AirporterFares");

        if (Page.IsValid)
        {
            try
            {
                // Save trip information.
                SysVarService.SharedRideTrip trip = new SysVarService.SharedRideTrip();

                if (_tripID > 0)
                    trip = Global.sysVarService.GetSharedRideTripByID(_tripID);

                trip.isVisible = 1;
                trip.productType = ReservationService.ProductType.TOUR;
                trip.originStopID = Convert.ToInt32(ddlOrigin.SelectedValue.ToString());
                trip.destinationStopID = Convert.ToInt32(ddlDestination.SelectedValue.ToString());
                trip.defaultDuration = 0;
                trip.effectiveDate = DateTime.Parse(tbxAirporterEffDate.Text.Trim());
                trip.startTimeOfDay = new DateTime(trip.effectiveDate.Year, trip.effectiveDate.Month, trip.effectiveDate.Day, 1, 1, 1);
                trip.endTimeOfDay = new DateTime(trip.effectiveDate.Year, trip.effectiveDate.Month, trip.effectiveDate.Day, 1, 1, 1);

                // Save the two fare information.
                SysVarService.SharedRideTrip_ShuttleFare aFare = new SysVarService.SharedRideTrip_ShuttleFare()
                {
                    effectiveDate = trip.effectiveDate,
                    effectiveTravelDate = trip.effectiveDate,
                    paxTypeID = 1,
                    oneWayCost = Foundation.StringFormatter.currencyToDouble(tbxAirporterAdultFare.Text.Trim()),
                    returnCost = 0.00,
                    numPax = 1,
                    Currency = 0
                };

                SysVarService.SharedRideTrip_ShuttleFare cFare = new SysVarService.SharedRideTrip_ShuttleFare()
                {
                    effectiveDate = trip.effectiveDate,
                    effectiveTravelDate = trip.effectiveDate,
                    paxTypeID = 2,
                    oneWayCost = Foundation.StringFormatter.currencyToDouble(tbxAirporterChildFare.Text.Trim()),
                    returnCost = 0.00,
                    numPax = 1,
                    Currency = 0
                };

                string status = "";

                if (_updating)
                    status = Global.sysVarService.UpdateAirporterFare(trip, aFare, cFare, GetScheduleEntries());
                else
                    status = Global.sysVarService.AddAirporterFare(trip, aFare, cFare, GetScheduleEntries());

                if (!String.IsNullOrEmpty(status))
                {
                    spanErrorMsg.Visible = true;
                    spanErrorMsg.InnerText = status;
                    return;
                }
            }
            catch (Exception ex)
            {
                spanErrorMsg.Visible = true;
                spanErrorMsg.InnerText = ex.ToString();
                return;
            }

            Response.Redirect("~/Internal/Admin/Default.aspx?action=Airporter_Fares");
        }

当我去添加或更新时,我调用GetScheduledEntries,它应该循环遍历数据表(从viewstate中获取它)并将模板化的字段转换为对象属性并将这些对象填充到列表中。

private List<AdminConfigService.SharedRideTimes> GetScheduleEntries()
{
    int idx = 0;

    List<AdminConfigService.SharedRideTimes> schedule = new List<AdminConfigService.SharedRideTimes>();

    if (gvAirporterSchedule.Rows.Count >= 1)
    {
        for (int i = 1; i <= gvAirporterSchedule.Rows.Count; ++i)
        {
            // Get data controls.
            DropDownList ddl = (DropDownList)gvAirporterSchedule.Rows[idx].Cells[0].FindControl("ddlScheduleLoc");

            TextBox startDate = (TextBox)gvAirporterSchedule.Rows[idx].Cells[1].FindControl("tbxAirporterStartDate");
            TextBox endDate = (TextBox)gvAirporterSchedule.Rows[idx].Cells[2].FindControl("tbxAirporterEndDate");
            TextBox deptTime = (TextBox)gvAirporterSchedule.Rows[idx].Cells[3].FindControl("tbxAirporterDepTime");
            TextBox duration = (TextBox)gvAirporterSchedule.Rows[idx].Cells[4].FindControl("tbxAirporterDuration");

            schedule.Add(new AdminConfigService.SharedRideTimes()
            {
                StartDate = DateTime.Parse(startDate.Text.Trim()),
                EndDate = DateTime.Parse(endDate.Text.Trim()),
                DepartureTime = DateTime.Parse(deptTime.Text.Trim()),
                Duration = Convert.ToInt32(duration.Text.Trim()),
                EffectiveDates = "",
                StopID = Convert.ToInt32(ddl.SelectedValue.ToString())
            });

            idx++;
        }

        return schedule;
    }
    else
        return schedule;
}

问题是,如果我从这个网格视图中删除行然后尝试保存表单,那么来自viewstate的数据表会带回那些已删除的行,并且就像它们仍然存在一样保存,即使gridview和数据表不再具有该行(当DeleteRow命令通过时)。

else if (e.CommandName == "DeleteRow")
    {
        SetRowData();

        if (ViewState["AirporterScheduleTable"] != null)
        {
            DataTable dt = (DataTable)ViewState["AirporterScheduleTable"];
            DataRow currentRow = null;

            GridViewRow gvr = (GridViewRow)(((Button)e.CommandSource).NamingContainer);
            int idx = gvr.RowIndex;

            if (dt.Rows.Count > 1)
            {
                dt.Rows.Remove(dt.Rows[idx]);
                currentRow = dt.NewRow();

                ViewState["AirporterScheduleTable"] = dt;

                gvAirporterSchedule.DataSource = dt;
                gvAirporterSchedule.DataBind();

                SetPreviousData();
            }
        }
    }

private void SetPreviousData()
{
    int idx = 0;

    if (ViewState["AirporterScheduleTable"] != null)
    {
        DataTable dt = (DataTable)ViewState["AirporterScheduleTable"];
        if (dt.Rows.Count > 0)
        {
            for (int i = 0; i < dt.Rows.Count; ++i)
            {
                // Get data controls.
                DropDownList ddl = (DropDownList)gvAirporterSchedule.Rows[idx].Cells[0].FindControl("ddlScheduleLoc");

                TextBox startDate = (TextBox)gvAirporterSchedule.Rows[idx].Cells[1].FindControl("tbxAirporterStartDate");
                TextBox endDate = (TextBox)gvAirporterSchedule.Rows[idx].Cells[2].FindControl("tbxAirporterEndDate");
                TextBox deptTime = (TextBox)gvAirporterSchedule.Rows[idx].Cells[3].FindControl("tbxAirporterDepTime");
                TextBox duration = (TextBox)gvAirporterSchedule.Rows[idx].Cells[4].FindControl("tbxAirporterDuration");

                ddl.SelectedValue = dt.Rows[i]["LocColumn"].ToString();
                startDate.Text = dt.Rows[i]["StartDateColumn"].ToString();
                endDate.Text = dt.Rows[i]["EndDateColumn"].ToString();
                deptTime.Text = dt.Rows[i]["DeptTimeColumn"].ToString();
                duration.Text = dt.Rows[i]["DurationColumn"].ToString();

                idx++;
            }
        }
    }
}

private void SetRowData()
{
    int idx = 0;

    if (ViewState["AirporterScheduleTable"] != null)
    {
        DataTable current = (DataTable)ViewState["AirporterScheduleTable"];
        DataRow currentRow = null;

        if (current.Rows.Count > 0)
        {
            for (int i = 1; i <= current.Rows.Count; ++i)
            {
                // Get data controls.
                DropDownList ddl = (DropDownList)gvAirporterSchedule.Rows[idx].Cells[0].FindControl("ddlScheduleLoc");

                TextBox startDate = (TextBox)gvAirporterSchedule.Rows[idx].Cells[1].FindControl("tbxAirporterStartDate");
                TextBox endDate = (TextBox)gvAirporterSchedule.Rows[idx].Cells[2].FindControl("tbxAirporterEndDate");
                TextBox deptTime = (TextBox)gvAirporterSchedule.Rows[idx].Cells[3].FindControl("tbxAirporterDepTime");
                TextBox duration = (TextBox)gvAirporterSchedule.Rows[idx].Cells[4].FindControl("tbxAirporterDuration");

                currentRow = current.NewRow();

                current.Rows[i - 1]["LocColumn"] = ddl.SelectedValue;
                current.Rows[i - 1]["StartDateColumn"] = startDate.Text;
                current.Rows[i - 1]["EndDateColumn"] = endDate.Text;
                current.Rows[i - 1]["DeptTimeColumn"] = deptTime.Text;
                current.Rows[i - 1]["DurationColumn"] = duration.Text;

                idx++;
            }

            ViewState["AirporterScheduleTable"] = current;
        }
    }
}

当我删除或向此动态网格视图添加条目时,似乎没有代码中的任何位置我没有更新ViewState数据表。什么可能导致ViewStates的差异? UpdatePanel和GridView外部按钮的完整回发是否具有不同的ViewState?

我也非常关注this tutorial

1 个答案:

答案 0 :(得分:0)

原来是你忽略一些简单的事情之一。当我使用加载数据填充网格时,我没有使用

保护它
if (!Page.IsPostback)

因此,每次删除行时,都会使用Page Load上的数据重新填充数据表,并导致删除的行似乎没有被删除的奇怪问题。