【问题标题】:c# How to utilize Page_init, ViewState and Page_Load properly?c# 如何正确使用Page_init、ViewState和Page_Load?
【发布时间】:2017-07-12 08:34:24
【问题描述】:

我使用 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 中重新填充吗?

【问题讨论】:

  • 我很惊讶警察还没有结束你的问题,因为你的问题太笼统了!无论如何,我无法在评论中提供有关 WebForms 的教程,但我会考虑将控件添加到页面标记中。例如,您可能有一个Repeater,其模板包含服务的所有按钮和范围。然后将Repeater DataBind 到包含有关您的服务的相关数据的对象列表。我会在模板中显示所有控件,并使用数据绑定表达式设置它们的可见性。例如。启动和停止按钮的可见性将由服务状态控制。
  • @Joe 我意识到标题有点笼统,我可以添加一个“在我的情况下”,但至少对我来说,情况似乎很明显。然而,问题本身显然集中在我的代码上,以及将其放在Page_Init 中而不是Page_Load 中会有什么好处。为什么以及如何影响 ViewState 以及我是否真的需要它。我还建议尝试实际答案,而不是“我无法在评论中提供有关 WebForms 的教程”。我什至还没有接触过中继器之类的东西(这就是我对 Webforms 的新认识),所以会得到一个彻底的答案。
  • @Skillzone,Markus 给出了一个很好的答案,我刚刚投了赞成票。基本上与上面的建议相同,但写得更好。避免动态创建控件,而是将控件包含在 ASPX 标记中,方法是使用中继器并根据需要设置控件的 Visible 属性。你说你还没有接触过中继器:如果是这样,我恭敬地建议你在尝试了解如何动态添加控件之前先了解中继器和数据绑定。
  • @Joe 我同意答案与您的评论相似,我只是对它发表了评论,要求提供更多信息。好吧,动态编程控件对我来说更自然,因为我来自严格的后端背景(Java 和 C)。因此,我试图尽可能地留在代码后面。因此,我的第一个谷歌搜索是关于学习如何从后面的代码中添加东西。我最近刚开始在搜索其他东西时遇到Repeater这个词,但没有进一步研究。

标签: c# asp.net viewstate pageload


【解决方案1】:

如果您不需要 ViewState,那么您也可以在 Page_Load 中创建控件。 ViewState 用于存储控件的值(哪些取决于控件)并在将 PostBack 发送到服务器时使用它们。

例如,如果您有一个文本框,则 PostBack 包含文本框的新值以及 ViewState 中的旧值。 ASP.NET 框架现在比较这两者并在必要时引发TextChanged 事件。如果没有 ViewState,这是不可能的。

对于在 ASP.NET WebForms 中动态创建的控件,您可以给出的最佳建议是避免使用它们。它们会非常快速地增加复杂性并且通常没有必要(即使一开始看起来如此)。

在大多数情况下,有一个更简单的方法,例如通过使用中继器。在您的情况下,您有一个服务列表。您可以将此列表绑定到中继器,从而避免手动创建控件。请参阅此link,了解如何使用中继器。

使用中继器的另一个好处是您可以在 ASPX 标记中定义 UI,而不是在代码隐藏文件中。在您的示例中,您根据服务的状态更改 UI。在这种情况下,使用中继器的ItemDataBound-event 可能是一个不错的选择。

【讨论】:

  • 中继器方法听起来更好。我对它们还不是很熟悉,现在正在阅读它们。我猜Page_Init 变得无关紧要了?由于控件将在 ASPX 标记和中继器中创建,并且数据绑定应该在 Page_Load 中完成,如果我没记错的话?
  • @Skillzore 你会发现Repeater 方法最终要简单得多。您将不再需要 Page_Init 和所有控件创建内容。通常,您在Page_Load 中设置中继器的DataSource。只有当您想根据数据本身更改布局时(在您的示例中有一个基于服务状态的 if 语句),您才需要使用ItemDataBound。我建议从小处着手,创建一个输出服务名称的Repeater,然后将通用服务布局添加到模板中,最后添加ItemDataBound
  • 是的,我在阅读它时已经开始尝试。只是想确保我没有放错数据绑定。到目前为止似乎运作良好。谢谢!不知道您对按钮和按钮事件的看法,但如果您对我有stackoverflow.com/q/45055878/6320872 的另一个问题提出意见,我将不胜感激。再次感谢!
猜你喜欢
  • 2011-10-08
  • 1970-01-01
  • 1970-01-01
  • 2019-02-02
  • 2011-04-30
  • 2011-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多