我遇到了一些问题,试图在作为用户控件(.ascx)文件一部分的向导中的回发之间保持文本框控件中的值状态。
一些背景
这是一个产品的订单,可以有不同的选项(1个产品可以有很多选项),因此选项不是通用的。 使用语法“OptionBox-4”(最后的数字为ID),向导的“开始”阶段向用户显示选项列表(使用SubSonic 2从数据库中提取)数据库中的选项,以便我可以稍后返回并获取说明。
然后,用户可以在每个选项中输入不同的数量。
问题
一旦用户在框中输入了数量,然后点击“下一步”,则不会在回发之间或控件的ID之间存储值。
代码
<asp:Wizard ID="Wizard1" runat="server" ActiveStepIndex="0"
DisplaySideBar="False" onnextbuttonclick="Wizard1_NextButtonClick"
onpreviousbuttonclick="Wizard1_PreviousButtonClick"
FinishCompleteButtonText="Submit request"
onfinishbuttonclick="Wizard1_FinishButtonClick"
onactivestepchanged="Wizard1_ActiveStepChanged"
onprerender="Wizard1_PreRender" >
<FinishPreviousButtonStyle CssClass="subbutton" />
<FinishCompleteButtonStyle CssClass="subbutton" />
<StartNextButtonStyle CssClass="subbutton" />
<StepNextButtonStyle CssClass="subbutton" />
<StepPreviousButtonStyle CssClass="subbutton" />
<WizardSteps>
<asp:WizardStep runat="server" StepType="Start" title="Description" ID="vgStep1">
<fieldset class="emailform">
<ul runat="server" id="optionList">
<asp:PlaceHolder id="DynamicBoxes" runat="server" />
</ul>
</fieldset>
</asp:WizardStep>
<asp:WizardStep ID="WizardStep1" runat="server" Title="Your details" StepType="Finish">
<h3>Order summary</h3>
<asp:Literal ID="ltlSummary" runat="server"></asp:Literal>
</asp:WizardStep>
<asp:WizardStep ID="WizardStep2" runat="server" StepType="Complete" Title="Thank you">
</asp:WizardStep>
</WizardSteps>
</asp:Wizard>
相关代码隐藏
class ResponseCollection : List<string> { }
private int? NrOfOptions
{
get { return (int?)ViewState["NrOfOptions"]; }
set { ViewState["NrOfOptions"] = value; }
}
public PartnerProductOrderableOptionCollection colOptions;
public PartnerProductOrderable prodOrderable;
protected void Page_Load(object sender, EventArgs e)
{
LoadOrderWizard(Utility.GetPartnerProductId(Request.QueryString["ppid"]));
CreateDynamicBoxes();
}
#region Ordering wizard
private void LoadOrderWizard(int p)
{
partnerProduct = new PartnerProduct(p);
prodOrderable = new PartnerProductOrderable("PartnerProductId", p);
colOptions = new PartnerProductOrderableOptionCollection();
colOptions.LoadAndCloseReader(PartnerProductOrderableOption.FetchByParameter("OrderableId", prodOrderable.OrderableId, OrderBy.Asc("ListOrder")));
if (!IsPostBack)
{
this.NrOfOptions = colOptions.Count;
}
}
protected void Wizard1_ActiveStepChanged(object sender, EventArgs e)
{
if (Wizard1.ActiveStepIndex == 1)
{
ResponseCollection responses = CollectValuesFromDynamicBoxes();
ltlSummary.Text += "Controls:";
foreach (Control c in DynamicBoxes.Controls)
{
ltlSummary.Text += c.ID + ",";
if (c is TextBox)
{
ltlSummary.Text += ((TextBox)c).ID + ",";
if (!String.IsNullOrEmpty(((TextBox)c).Text))
{
int optionid = int.Parse(c.ID.Split('-')[1]);
PartnerProductOrderableOption o = new PartnerProductOrderableOption(optionid);
ltlSummary.Text += "<strong>Quantity: </strong>" + ((TextBox)c).Text + "<br />";
ltlSummary.Text += "<strong>Description: </strong>" + o.Description + " - " + o.Price + "<hr />";
}
}
}
}
}
protected void Wizard1_PreviousButtonClick(object sender, WizardNavigationEventArgs e)
{
}
protected void Wizard1_FinishButtonClick(object sender, WizardNavigationEventArgs e)
{
ResponseCollection responses = CollectValuesFromDynamicBoxes();
}
protected void Wizard1_NextButtonClick(object sender, WizardNavigationEventArgs e)
{
if (e.CurrentStepIndex == 0)
{
int newNumberOfOptions = colOptions.Count;
int? oldNumberOfOptions = this.NrOfOptions;
if (!oldNumberOfOptions.HasValue || newNumberOfOptions != oldNumberOfOptions.Value)
{
this.NrOfOptions = newNumberOfOptions;
CreateDynamicBoxes();
}
}
}
private void CreateDynamicBoxes()
{
if (!this.NrOfOptions.HasValue)
return;
DynamicBoxes.Controls.Clear();
foreach (PartnerProductOrderableOption opt in colOptions)
{
HtmlGenericControl li = new HtmlGenericControl("li");
DynamicBoxes.Controls.Add(li);
TextBox box = new TextBox();
box.ID = "OptionBox-" + opt.OptionId;
box.Width = 40;
box.MaxLength = 6;
li.Controls.Add(box);
Label lblOpt = new Label();
lblOpt.ID = "lblOption-" + opt.OptionId;
lblOpt.Text = opt.Description + " - " + opt.Price;
li.Controls.Add(lblOpt);
}
this.NrOfOptions= colOptions.Count;
}
private ResponseCollection CollectValuesFromDynamicBoxes()
{
ResponseCollection responses = new ResponseCollection();
for (int i = 0; i < this.NrOfOptions.Value; i++)
{
TextBox box = (TextBox)DynamicBoxes.FindControl("OptionBox-" + i);
string response = box.Text.Trim();
if (response.Length > 0)
responses.Add(response);
}
return responses;
}
protected void Wizard1_PreRender(object sender, EventArgs e)
{
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
}
#endregion
代码基于http://aspnetresources.com/blog/dynamic_text_bBoxes_in_wizard_control,它似乎与我需要的东西非常相似。
另一个注释
必须在Page_Load事件中调用LoadOrderWizard方法。这是一个精简代码,只显示与我的问题相关的代码。控件实际上由几个不同的面板组成,这些面板根据传递给控件的数据显示不同的信息。因此,Page_Init事件中的初始化代码将不必要地触发。
答案 0 :(得分:0)
尝试将CreateDynamicBoxes()移动到Page_Init
protected void Page_Init(object sender, EventArgs e)
{
CreateDynamicBoxes();
}
答案 1 :(得分:0)
最后,因为我找不到一个可行的解决方案,我最终使用会话变量来存储动态框的id和包含的值。然后我在其他页面上检查文本框ID是否包含在会话中,并将其值恢复到框中。
由于只有数字放在此框中,此解决方案对我来说是一种解决方法。但是,知道是否有另一种解决方案仍然很好。