2016-08-13 44 views
1

我正在開發一個原始爲Visual Studio網站項目的舊網站,並將其轉換爲Web應用程序以及其他工作。網站上的一個頁面使用GridView,並使用DataTable在代碼隱藏中設置DataSource。 GridView暴露了幾個BoundFields,以及一個有一個複選框的TemplateField。 GridView被配置爲使用EnableViewState。asp.net GridView是否有能力使用ViewState?

<asp:GridView ID="Results" runat="server" AutoGenerateColumns="False" CellPadding="4" ForeColor="#333333" GridLines="None" EnableViewState="true"> 
    <AlternatingRowStyle BackColor="White" ForeColor="#284775" /> 
    <Columns> 
     <asp:BoundField DataField="Type" HeaderText="Type"/> 
     <asp:BoundField DataField="ProcessDate" HeaderText="Process Date" /> 
     <asp:BoundField DataField="Classification" HeaderText="Classification" /> 
     <asp:BoundField DataField="Email" HeaderText="Email" /> 
     <asp:TemplateField HeaderText="Notify?" ItemStyle-HorizontalAlign="Center"> 
      <EditItemTemplate> 
       <asp:CheckBox ID="CheckBox1" runat="server" onclick="EnableSubmit(this);" /> 
      </EditItemTemplate> 
      <ItemTemplate> 
       <asp:CheckBox ID="CheckBox1" runat="server" onclick="EnableSubmit(this);" /> 
      </ItemTemplate> 
     </asp:TemplateField> 
    </Columns> 
</asp:GridView> 

頁也有一個提交按鈕,並在_Click處理程序,代碼試圖搶Results.Rows,然後以確定哪些行已被他們選中的複選框周圍挖。它根據選中的行進行後續處理。

  • 舊的站點代碼沒有IsPostBack檢查,並且只在DataBind爲false時才調用它。
  • 的頁面不定義任何的EnableViewState或ViewStateMode,這意味着他們都默認設置爲true,根據MSDN。
  • 在母版頁或其他任何地方都沒有對DataBind的調用。
  • 舊的站點代碼不會執行任何手動保存到ViewState字典。
  • 令人驚訝的是,這個網站的生產版本實際上工作。

由於我一直在處理這個問題,我只找到線程和文章來討論GridView如何不實際使用ViewState,以及如何使用發送給用戶的數據,DataTable用作數據源必須手動插入的ViewState在後面的代碼等

我的工作已被轉換爲一個Web應用程序項目現場的版本,它的目標.NET 4.5。當我調試該網站並在Page_LoadSubmit_Click中斷時,Results GridView具有一個空數據源,並且Rows屬性具有0個計數。這似乎與目前關於GridView「如何工作」的傳統觀點一致。

我很清楚地知道,對於這個網站是幹什麼的,這是一個令人髮指的實現,並有更好的方法來做到這一點。然而,我最關心的是我無法找到任何關於舊版本如何工作的解釋。

難道在其歷史忽略其EnableViewState屬性某些時候GridView的變化?實際上,GridView上的EnableViewState是做什麼的?它可能是網站和Web應用程序項目之間的區別嗎?

這可能如何工作?

更新:根據伯特埃文斯例如頁面上,我嘗試了這種修改過的頁面。

<%@ Page Language="C#" %> 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

<script runat="server"> 
    public class Thing 
    { 
     public int ID { get; set; } 
     public string Name { get; set; } 
    } 
    IEnumerable<Thing> Things 
    { 
     get 
     { 
      var things = new List<Thing>(); 
      things.Add(new Thing { ID = 1, Name = "One" }); 
      things.Add(new Thing { ID = 2, Name = "Two" }); 
      things.Add(new Thing { ID = 3, Name = "Three" }); 
      things.Add(new Thing { ID = 4, Name = "Four" }); 
      things.Add(new Thing { ID = 5, Name = "Five" }); 
      return things; 
     } 
    } 

    void Page_Load(object sender, EventArgs e) 
    { 
     if (!IsPostBack) 
     { 
      ThingGridView.DataSource = Things; 
      ThingGridView.DataBind(); 
     } 

     pageLoadLabel.Text = string.Format("On page Load, row count: '{0}'", ThingGridView.Rows.Count); 
    } 

    void OnClickMe(object sender, EventArgs e) 
    { 
     onClickLabel.Text = string.Format("On click, row count: '{0}'", ThingGridView.Rows.Count); 
    } 

</script> 

<html xmlns="http://www.w3.org/1999/xhtml"> 
<head runat="server"> 
    <title></title> 
</head> 
<body> 
    <form id="form1" runat="server"> 
    <div> 
     <asp:GridView runat="server" ID="ThingGridView"> 
      <Columns> 
       <asp:BoundField HeaderText="Name" DataField="Name" /> 
      </Columns> 
     </asp:GridView> 
    </div> 
     <asp:Button runat="server" ID="ThingButton" Text="Click Me!" OnClick="OnClickMe" /> 
     <asp:Label runat="server" ID="onClickLabel" Text="[set on click]" /> 
     <asp:Label runat="server" ID="pageLoadLabel" Text="[set on page load]" /> 
    </form> 
</body> 
</html> 

唯一的區別是在頁面主體中打印出行數的標籤。執行此頁面時。第一次Page_Load調用會在頁面上打印行數5;但是,在回發中,頁面加載和OnClick方法中的行計數均爲0。

+0

只需查看頁面的HTML標記中的視圖狀態即可。打開和關閉啓用視圖狀態並查看差異。 – mason

+0

你是說它在生產版本中有效,但不是在你的產品中? – Bert

+0

@BertEvans是的 - 在某些方面,舊版本在回發處理期間管理從GridView的Rows屬性中提取數據,除了在數據層中劃分出一些SQL訪問權限之外,所有已更改的內容都將升級項目到Web應用程序(並可能使用更新的.NET版本)。 – bwerks

回答

1

感謝Bert Evans和他的例子頁面,我最終孤立了這個問題。該錯誤實際上是UnityHttpModule的MSDN代碼示例非常差,它將Unity DI與ASP.NET集成在一起。 UnityHttpModule詳述於https://msdn.microsoft.com/en-us/library/ff664534(v=pandp.50).aspx

除了實際上並沒有像列出的那樣編譯以外,類在InitComplete事件上連接了DI代碼,該事件發生在ViewState加載之前,如本文所述:ASP.NET 4.0 GridView OnRowEditing events not firing when using Unity 2.0 http module。在我的情況下,移動DI代碼在PreLoad上執行解決了我的問題。

最後,爲了完整起見,以及對MSDN Unity DI HttpModule存在問題的其他人,不同的SO線程也提供了一個工作示例:ASP.NET Dependency Injection HTTP Module (MS Enterprise Library)

1

數據綁定是平移所述數據源指定爲一個控制成呈現給網頁的控制樹的過程。對於GridView,本質上,設置DataSource屬性並調用DataBind方法會將從另一個源(如DataSetDataTable)提取的IEnumerableIEnumerable轉換爲包含數據的控件的HTML表。

每個渲染到表格單元格的控件維護它自己的ViewState,這樣當頁面回發到服務器時,GridView重建的控制結構,並與在ViewState數據填充控件(或者更確切地說,頁面啓動控制結構的重建,GridView只是參與)。

DataSource未保存到ViewState,只有呈現的控件的狀態。

GridView上禁用ViewState可防止它保存某些自身狀態的元素,從而導致它無法執行分頁和排序等操作。此外,如果您在GridView上禁用ViewState,並且執行回發(在客戶端觸發將頁面提交回服務器的事件),那麼GridView將在頁面重新呈現時不顯示任何內容,因爲EnableViewState被繼承,並且子控件將被阻止保存自己的狀態。使使用禁用的ViewState在回發後再次顯示數據的唯一方法是重新綁定數據(再次呼叫DataBind與有數據的數據源)或手動啓用ViewState包含的子控件在GridView的內部禁用ViewState。您提到您正在處理的頁面上的DataBind!IsPostback保護,因此它僅在頁面的初始加載時纔有約束力。

我不知道有什麼改變,使GridView在一個時間點保存DataSource,我相信這是它總是如何工作。

+0

最終,這個問題最終成爲微軟的MSDN UnityHttpModule代碼,但我已經提出了你的回覆,感謝你的幫助!沒有它,我不會想到這一點。 – bwerks

+0

@bwerks我很高興你能想出來。我已將您對我的示例頁面的修改複製到了我的框中,並且它按預期工作,所以我對如何幫助未來感到不知所措。雖然很好找! – Bert