c# 如何正确使用Page_init、ViewState 和Page_Load?
c# How to utilize Page_init, ViewState and Page_Load properly?
我使用 Web 表单已经有一段时间了,我已经阅读了我在 google 上找到的大部分内容。但是,我仍然不清楚如何正确使用它。我喜欢 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
s 和 HtmlButton
s 的私有全局列表感觉很不干净。
我知道 ViewState 在 Page_Init 和 Page_Load 之间加载,但这到底是什么意思?由于我不进行完整的回发,而是使用 RegisterAsyncPostBackControl
仅在回发时更新 UpdatePanel
,我不需要在 Page_Load 中重新填充吗?
如果您不需要ViewState,那么您也可以在Page_Load
中创建控件。 ViewState 用于存储控件的值(哪些控件取决于控件)并在将 PostBack 发送到服务器时使用它们。
例如,如果您有一个文本框,则 PostBack 包含文本框的新值以及 ViewState 中的旧值。 ASP.NET 框架现在比较这两者并在必要时引发 TextChanged
事件。如果没有 ViewState,这是不可能的。
关于在 ASP.NET WebForms 中动态创建的控件,您可以提供的最佳建议是避免使用它们。它们会非常快速地增加复杂性并且通常没有必要(即使一开始看起来是这样)。
在大多数情况下,有一种更简单的方法,例如通过使用中继器。在您的情况下,您有一个服务列表。您可以将此列表绑定到 Repeater,从而避免手动创建控件。请参阅 link 了解如何使用 Repeater。
使用 Repeater 的另一个好处是您可以在 ASPX 标记而不是代码隐藏文件中定义 UI。在您的示例中,您根据服务状态更改 UI。在这种情况下,使用 Repeater 的 ItemDataBound 事件可能是一个不错的选择。
我使用 Web 表单已经有一段时间了,我已经阅读了我在 google 上找到的大部分内容。但是,我仍然不清楚如何正确使用它。我喜欢 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
s 和 HtmlButton
s 的私有全局列表感觉很不干净。
我知道 ViewState 在 Page_Init 和 Page_Load 之间加载,但这到底是什么意思?由于我不进行完整的回发,而是使用 RegisterAsyncPostBackControl
仅在回发时更新 UpdatePanel
,我不需要在 Page_Load 中重新填充吗?
如果您不需要ViewState,那么您也可以在Page_Load
中创建控件。 ViewState 用于存储控件的值(哪些控件取决于控件)并在将 PostBack 发送到服务器时使用它们。
例如,如果您有一个文本框,则 PostBack 包含文本框的新值以及 ViewState 中的旧值。 ASP.NET 框架现在比较这两者并在必要时引发 TextChanged
事件。如果没有 ViewState,这是不可能的。
关于在 ASP.NET WebForms 中动态创建的控件,您可以提供的最佳建议是避免使用它们。它们会非常快速地增加复杂性并且通常没有必要(即使一开始看起来是这样)。
在大多数情况下,有一种更简单的方法,例如通过使用中继器。在您的情况下,您有一个服务列表。您可以将此列表绑定到 Repeater,从而避免手动创建控件。请参阅 link 了解如何使用 Repeater。
使用 Repeater 的另一个好处是您可以在 ASPX 标记而不是代码隐藏文件中定义 UI。在您的示例中,您根据服务状态更改 UI。在这种情况下,使用 Repeater 的 ItemDataBound 事件可能是一个不错的选择。