2017-07-12 120 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