ViewState 中的 DataTable 返回已删除的行

本文关键字:删除 返回 中的 DataTable ViewState | 更新日期: 2023-09-27 18:35:21

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

我的网格视图标记是这样的:

<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>

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

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,它应该遍历数据表(从视图状态中获取它)并将模板化字段转换为对象属性并将这些对象填充到列表中。

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

问题是,如果我从此网格视图中删除行,然后尝试保存表单,则视图状态中的数据表会带回这些已删除的行,并表现得好像它们仍然存在以进行保存,即使网格视图和数据表不再具有该行(当 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 数据表。导致视图状态差异的原因是什么?在 UpdatePanel 和 GridView 外部的按钮的完整回发是否具有不同的视图状态?

我也完全遵循了本教程。

ViewState 中的 DataTable 返回已删除的行

事实证明,这是您忽略简单事物的情况之一。当我用加载数据填充网格时,我没有使用

if (!Page.IsPostback)

因此,每次删除该行时,它都会在页面加载时使用数据重新填充数据表,并导致删除的行似乎没有被删除的奇怪问题。