我目前正在开发一个动态网格视图,允许用户添加或删除行,以便以后保存为数据库条目。
我的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。
答案 0 :(得分:0)
原来是你忽略一些简单的事情之一。当我使用加载数据填充网格时,我没有使用
保护它if (!Page.IsPostback)
因此,每次删除行时,都会使用Page Load上的数据重新填充数据表,并导致删除的行似乎没有被删除的奇怪问题。