我现在已经使用Web Forms了一段时间,我已经在谷歌上阅读了大部分关于此的内容。但是,我仍然不清楚如何正确使用它。我喜欢this answer中的图片,但发现它有点过于通用。关于如何处理这些事件,我没有找到一个体面的具体例子。
我目前正在Page_Load事件中的代码中动态创建多个控件:
foreach (Service service in Services)
{
// service div
HtmlGenericControl serviceDiv = new HtmlGenericControl("div");
serviceDiv.ID = service.ID;
serviceDiv.Style.Add(HtmlTextWriterStyle.TextAlign, "center");
outerDiv.Controls.Add(serviceDiv); //outerDiv exists in the aspx page
// service updatepanel
UpdatePanel uPanel = new UpdatePanel()
{
ID = service.ID + "_uPanel",
UpdateMode = UpdatePanelUpdateMode.Conditional
};
serviceDiv.Controls.Add(uPanel);
// status span
HtmlGenericControl statusSpan = new HtmlGenericControl("span");
statusSpan.ID = service.ID + "_statusSpan";
statusSpan.InnerHtml = service.Status;
uPanel.ContentTemplateContainer.Controls.Add(statusSpan);
// show specific content
if (service.Status.Equals(ServiceControllerStatus.Running.ToString()))
{
// status color
statusSpan.Attributes.Add("class", "status-run");
// stop button
HtmlButton stopButton = new HtmlButton();
stopButton.ID = service.ID + "_btnStop";
stopButton.InnerHtml = "<i class=\"fa fa-stop btn-red\"/></i>";
stopButton.Attributes.Add("type", "button");
stopButton.Attributes.Add("runat", "server");
stopButton.Attributes.Add("class", "btn btn-link btn-xs");
stopButton.Attributes.Add("title", "Stop");
stopButton.ServerClick += new EventHandler(BtnStop_Click);
ScriptManager.GetCurrent(this).RegisterAsyncPostBackControl(stopButton);
uPanel.ContentTemplateContainer.Controls.Add(stopButton);
// restart button
HtmlButton restartButton = new HtmlButton();
restartButton.ID = service.ID + "_btnRestart";
restartButton.InnerHtml = "<i class=\"fa fa-refresh btn-blue\"/></i>";
restartButton.Attributes.Add("type", "button");
restartButton.Attributes.Add("runat", "server");
restartButton.Attributes.Add("class", "btn btn-link btn-xs");
restartButton.Attributes.Add("title", "Restart");
restartButton.ServerClick += new EventHandler(BtnRestart_Click);
ScriptManager.GetCurrent(this).RegisterAsyncPostBackControl(restartButton);
uPanel.ContentTemplateContainer.Controls.Add(restartButton);
}
else
{
// status color
statusSpan.Attributes.Add("class", "status-stop");
// start button
HtmlButton startButton = new HtmlButton();
startButton.ID = service.ID + "_btnStart";
startButton.InnerHtml = "<i class=\"fa fa-play btn-green\"/></i>";
startButton.Attributes.Add("type", "button");
startButton.Attributes.Add("runat", "server");
startButton.Attributes.Add("class", "btn btn-link btn-xs");
startButton.Attributes.Add("title", "Start");
startButton.ServerClick += new EventHandler(BtnStart_Click);
ScriptManager.GetCurrent(this).RegisterAsyncPostBackControl(startButton);
uPanel.ContentTemplateContainer.Controls.Add(startButton);
}
// version span
HtmlGenericControl versionSpan = new HtmlGenericControl("span");
versionSpan.ID = service.ID + "_version";
versionSpan.InnerHtml = service.Version;
versionSpan.Attributes.Add("class", "version-text");
serviceDiv.Controls.Add(versionSpan);
在Page_Init中创建这些内容我会得到什么?如果我在Page_Init中创建它们,我如何在Page_Load中访问它们? UpdatePanel
和HtmlButton
的私人全球列表感觉非常不洁净。
我知道ViewState在Page_Init和Page_Load之间加载,但这究竟意味着什么?由于我不做完整的回发,而是使用RegisterAsyncPostBackControl
仅在回发时更新UpdatePanel
,我不需要在Page_Load中重新填充?
答案 0 :(得分:2)
如果您不需要ViewState,则还可以在Page_Load
中创建控件。 ViewState用于存储控件的值(取决于控件的值),并在PostBack发送到服务器时使用它们。
例如,如果您有一个文本框,则PostBack包含文本框的新值以及ViewState中的旧值。 ASP.NET框架现在比较这两个,并在必要时引发TextChanged
事件。没有ViewState,这是不可能的。
对于ASP.NET WebForms中动态创建的控件,您可以提供的最佳建议是避免使用它们。它们非常快速地增加复杂性并且通常不是必需的(即使它最初看起来如此)。
在大多数情况下,有一种更简单的方法,例如通过使用中继器。在您的情况下,您有一个服务列表。您可以将此列表绑定到Repeater,并避免手动创建控件。有关如何使用Repeater的信息,请参阅此link。
使用Repeater的另一个好处是,您可以在ASPX标记中而不是在代码隐藏文件中定义UI。在您的示例中,您可以根据服务的状态更改UI。在这种情况下,使用Repeater的ItemDataBound - 事件可能是一个不错的选择。