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 中访问它们? UpdatePanels 和 HtmlButtons 的私有全局列表感觉很不干净。

我知道 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 事件可能是一个不错的选择。