[英]DataTable in ViewState is Returning Deleted Rows
我目前正在動態網格視圖上,該視圖將允許用戶添加或刪除行,以便以后保存為數據庫條目。
我的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>
除了該網格外,用戶控件中還有其他一些字段。 當我保存時,用戶將單擊用戶控件底部的按鈕,該按鈕會將其上方的表單字段和網格打包為一些類,並將其打包到數據庫代碼中以添加/更新此數據。
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;
}
問題是,如果我從此網格視圖中刪除行,然后嘗試保存表單,則視圖狀態中的數據表將帶回那些已刪除的行,並且它們的行為就像它們仍然存在以進行保存,即使網格視圖和數據表不存在擁有該行了(當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;
}
}
}
在此動態gridview中刪除或添加條目時,似乎沒有任何代碼可以更新ViewState數據表。 是什么引起ViewStates的差異? UpdatePanel和GridView外部的按鈕的完整回發是否具有不同的ViewState?
我也幾乎完全遵循了本教程 。
原來是您忽略一些簡單事情的情況之一。 當我用加載的數據填充網格時,我並沒有使用
if (!Page.IsPostback)
因此,每次刪除該行時,它都會用Page Load上的數據重新填充數據表,並導致一些奇怪的問題,其中似乎沒有刪除已刪除的行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.