我正在尝试构建一个服务器控件,根据“QuestionTypeId”显示文本框、日期选择器或是-否单选按钮。
我的控件显示了我想要的方式,但是当在表单上按下提交按钮时,在 RenderContents 方法中生成的文本框、日期选择器或单选按钮都为空。
我试图将生成的控件存储在视图状态中,这阻止了它们为空,但没有存储用户输入。
如果需要,我会发布代码。问一下。
我正在尝试构建一个服务器控件,根据“QuestionTypeId”显示文本框、日期选择器或是-否单选按钮。
我的控件显示了我想要的方式,但是当在表单上按下提交按钮时,在 RenderContents 方法中生成的文本框、日期选择器或单选按钮都为空。
我试图将生成的控件存储在视图状态中,这阻止了它们为空,但没有存储用户输入。
如果需要,我会发布代码。问一下。
我认为您需要在CreateChildControls中创建(并添加)控件。这意味着您需要将 QuestionTypeId 的值存储在 Viewstate 或 ControlState 中(我认为 ControlState 在这种情况下适用,因为如果没有此值,您的控件将无法工作)。
一种更简单的方法是在设计时创建所有控件,并根据您的要求使控件不可见。
示例代码:
protected void Page_Load(object sender, EventArgs e)
{
txtBox.Visible = QuestionTypeID == 1;
chkBox.Visible = QuestionTypeID == 2;
}
如果您确实使用动态控件,您应该按照 David 指出的那样做,将值 QuestionTypeID 保存在 ViewState 或 ControlState 中,然后根据该值创建所需的控件。
(每次页面加载时都需要创建控件,即使在回发时也需要创建它们,并且它们不能在页面生命周期的后期创建,如果您希望它们的 ViewState 持久化和恢复,则使用 Page_Load 方法)
示例代码:
protected void Page_Load(object sender, EventArgs e)
{
var questionId = ViewState["QuestionTypeID"];
if(questionId == /* Value to create TextBox */) {
var txt = new TextBox { ID = "txt" };
placeHolder.Controls.Add(txt);
} else if(questionId == /* Value to create Calender */) {
var cal = new Calender { ID = "cal" };
placeHolder.Controls.Add(cal);
}
/* Once the controls are added they will be populated with the posted values */
}
PS
使用动态控件指定 ID 总是一个好主意。
您可以将添加的控件保存到成员变量并在其他地方使用它们(在分配它们之后)
您可以订阅他们的事件,如果用户发布了一个新值,您的方法将被调用
我听从了您的建议并做了以下事情:
1)问题类型存储在我的服务器控件的视图状态中。
2) 现在在 CreateChildControls 上创建我的控件的新实例并将其添加到页面上的占位符。
我现在的问题是事情似乎有点奇怪:
1)在页面初始加载时,会触发创建子控件,并触发我的服务器控件的 RenderContents 方法。
2)单击按钮以加载新联系人,这会触发创建子控件并触发 RenderContents。
3)输入详细信息并按下保存,这会触发 Create Child Controls 但不会触发 RenderContents 并且通过尝试访问我的控件以获取值来生成 NullReferenceException。(如果我跳过访问我的控件的代码,则会调用 RenderContents 并进行渲染。
其次,另一个问题是,当我尝试设置一个值(onDataBind)时,我尝试访问在我的服务器控件中生成的文本框并获取另一个 NullReferanceExeption
想法?
当您动态添加控件时,您需要确保在恢复视图状态之前重新创建它们。
我有一段时间没有这样做了,但从记忆中我认为你应该在 OnInit 方法中重新创建你的控件。这发生在加载回发数据之前以及控件从视图状态设置其值之前。
关于 asp.net 页面生命周期可能值得阅读:
您可以为文本框、日期选择器、单选按钮创建用户控件并使用服务器控件。
如果您创建一个自定义服务器控件,那么您必须将发布的数据添加到您的控件属性中。您可以在您的控制 OnInit 事件中执行此操作:
MyProperty = Request.Form("myControl");