2017-07-12 119 views
2

我一直在使用Web Forms一段时间,现在我已阅读了大部分我在Google上发现的相关内容。但是,我仍然不清楚如何正确处理这个问题。我喜欢this answer中的图片,但发现它有点过于通用。我还没有找到一个体面的,具体的例子来说明如何处理这些事件。c#如何正确使用Page_init,ViewState和Page_Load?

我在代码中动态在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?

+0

我很惊讶警方没有围着你的问题过于笼统!无论如何,我无法在评论中给出关于WebForms的教程,但我会考虑将控件添加到页面标记中。例如,您可能有一个Repeater,其模板包含服务的所有按钮和跨度。然后将数据绑定到包含有关您的服务的相关数据的对象列表。我将使模板中存在所有控件,并使用数据绑定表达式设置其可见性。例如。开始和停止按钮的可见性将由服务状态控制。 – Joe

+0

@Joe我意识到标题有点泛泛,我可以添加一个“以我的情况”,但似乎很明显,至少对我来说是这种情况。然而,问题本身显然集中在我的代码上,将它放在'Page_Load'上的'Page_Init'中会带来什么好处。为什么以及如何影响ViewState,以及我是否真的需要它。 我也建议在实际的答案,而不是与“我不能给一个评论中的WebForms的教程”去。我甚至没有转发器等等(这对Webforms来说是多么的新鲜),所以一个彻底的答案将会受到重视。 – Skillzore

+0

@Skillzone,马库斯给出了一个很好的答案,我刚刚提出。基本上与上述相同的建议,但写得更好。避免动态创建控件,而是将控件包含在ASPX标记中,使用Repeater并根据需要设置控件的Visible属性。你说你还没有得到中继器:如果是这样的话,我建议你在尝试了解如何动态添加控件之前先学习中继器和数据绑定。 – Joe

回答

2

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

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

有关ASP.NET WebForms中动态创建控件的最佳建议是避免使用它们。它们非常快速地增加了复杂性,通常不是必需的(即使它起初看起来如此)。

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

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

+0

中继器的方法确实听起来更好。我还没有真正熟悉它们,现在就阅读它们。我猜这个'Page_Init'变得不相关了?由于控件将在ASPX标记和Repeater中创建,并且数据绑定应该在'Page_Load'中完成,如果我没有弄错的话? – Skillzore

+0

@Skillzore你会发现Repeater的方法最终要简单得多。你不再需要'Page_Init'和所有的控件创建工具。通常,您在'Page_Load'中设置Repeater的'DataSource'。只有当你想根据数据本身来改变布局时(在你的示例中有一个基于服务状态的if语句),你需要使用'ItemDataBound'。我建议从小开始,创建一个输出服务名称的Repeater,然后将公共服务布局添加到模板中,最后添加'ItemDataBound'。 – Markus

+0

是的,我已经开始尝试一些了解它。只是想确保我没有放错数据绑定。似乎目前运作良好。谢谢! 不知道你是如何与按钮和按钮事件,但我将不胜感激您对我有https://stackoverflow.com/q/45055878/6320872的另一个问题的意见。再次感谢! – Skillzore