【问题标题】:Enable ViewState for few controls and disable for others/page为少数控件启用 ViewState 并为其他/页面禁用
【发布时间】:2008-10-09 10:21:32
【问题描述】:

当我禁用页面的 ViewState 时。它不允许任何其他控件使用 ViewState .. 即使我为该特定控件设置 EnableViewState="true" ..

当页面本身的 ViewState 被禁用时,是否可以为控件启用 ViewState?

如果不是,如何禁用页面上控件的视图状态,除了少数没有明确指定 EnableViewState="false" .. 在这么多控件中输入相同内容是忙碌的 ..

【问题讨论】:

    标签: c# asp.net viewstate


    【解决方案1】:

    如果您设置关闭页面的 ViewState,那么您将无法为特定组件启用 ViewState。这是因为 ViewState 是递归序列化的,所以当 Page 不允许 ViewState 时,它​​不会为它的任何子控件序列化 ViewState。

    在回答您的问题时,如果您不想在单个控件上显式关闭 ViewState,但希望保持某些控件的 ViewState 感知,最好的方法是编写一个小的实用程序方法来关闭所有控件的 ViewState (使用递归或其他方式)。然后为您要为其启用 ViewState 的控件启用 ViewState。

    或者,如果控件是其他容器控件(例如 Panel)内的组,则可以采用一种中间立场且不那么有力的方式。您可以通过禁用 Panel 的 ViewState 来禁用 Panel 内所有控件的 ViewState。

    【讨论】:

    • 同样的概念是否适用于占位符?这样就可以解决生成过多 HTML 标记的问题。
    • 占位符只对文本内容有用。如果你有一个日历控件并且不想拥有 ViewState,那么你不想使用 Placeholder 并编写日历 HTML。
    • 当然是选项,但是关闭容器的视图状态会关闭所有子控件的视图状态,包括标签。
    • 在 .NET 4 中,您可以关闭 ViewState,但如果您为控件设置 ViewStateMode=Enabled,即使页面有它禁用了msdn.microsoft.com/en-us/library/vstudio/…
    【解决方案2】:

    如果你关闭了翻页的 ViewState, 那么您将无法启用 特定组件的 ViewState。 这是因为 ViewState 是序列化的 递归地,所以当页面是 不允许 ViewState,它不会 为任何一个序列化 ViewState 它是子控件。它是子控件。

    随着 ASP.NET 4 的出现,我们有了一个名为 ViewStateMode 的新属性,即使页面的视图状态被禁用,它也可用于启用单个控件的视图状态。

    要使用这个新属性,您可以创建一个将 ViewStateMode 设置为 Disabled 的基本页面类,也可以创建一个执行相同操作的 PageAdapter。 web.config 中没有 viewStateMode 属性。

    这是页面适配器的代码:

    using System.Web.UI;
    using System.Web.UI.Adapters;
    
    namespace Playground.Web.UI.Adapters
    {
        public class PageAdapter: System.Web.UI.Adapters.PageAdapter
        {
            protected override void OnLoad(EventArgs e)
            {
                ViewStateMode = ViewStateMode.Disabled;
                base.OnLoad(e);
            }
        }
    }
    

    这是浏览器文件的代码:

    <browser refID="default">
        <controladapters>
            <adapter controlType="System.Web.UI.Page" adapterType="Playground.Web.UI.Adapters.PageAdapter" />
        </controladapters>
    </browser>
    

    【讨论】:

      【解决方案3】:

      这里有一些代码扩展了@Samuel Kim 的概念,即有一种方法可以在除某些控件之外的所有控件上禁用 ViewState(顺便说一句,它使用 .NET 3.5):

      List<string> allowedControls = new List<string> { "Control1", "Control3" };
      IEnumerable<Control> controlsWithoutViewState = Page.Controls.Where(c => !allowedControls.Contains(c.ID));
      foreach(Control c controlsWithoutViewState){
        if(c is WebControl) ((WebControl)c).EnableViewState = false;
      }
      

      唯一我不能 100% 确定(而且我没有运行我的虚拟机)是 Page.Controls 是否需要强制转换,如果需要,就改用这个:

      IEnumerable<Control> controlsWithoutViewState = Page.Controls.Cast<Control>().Where(c => !allowedControls.Contains(c.ID));
      

      上面只是一个快速的概念,它没有考虑嵌套控件,你可能想要 1 和 1 没有 ViewState,但创建一个递归函数来处理它并不难.

      【讨论】:

      • 在 foreach 中缺少 in
      【解决方案4】:

      使用 .NET 4.0,您还可以定义控制适配器

      namespace BB.Common.UI.Adapters
      {
          [AspNetHostingPermission(System.Security.Permissions.SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
          public class DisableViewStateControl : System.Web.UI.Adapters.ControlAdapter
          {
              protected override void OnInit(EventArgs e)
              {
                  if (Control.ViewStateMode == ViewStateMode.Inherit)
                      Control.ViewStateMode = ViewStateMode.Disabled;
                  base.OnInit(e);
              }
          }
      }
      

      在上面的代码中,ViewState 模式在继承时被禁用。在浏览器设置文件中添加以下行。

      <browsers>
        <browser refID="Default" >
          <controlAdapters>
            <adapter
                controlType="System.Web.UI.WebControls.Label"
                adapterType="Fiserv.Common.UI.Adapters.DisableViewStateControl" />
            <adapter
               controlType="System.Web.UI.WebControls.HyperLink"
               adapterType="Fiserv.Common.UI.Adapters.DisableViewStateControl" />
            <adapter
               controlType="System.Web.UI.WebControls.ImageButton"
               adapterType="Fiserv.Common.UI.Adapters.DisableViewStateControl" />
            <adapter
                controlType="System.Web.UI.WebControls.Button"
                adapterType="Fiserv.Common.UI.Adapters.DisableViewStateControl" />
          <adapter
                controlType="System.Web.UI.WebControls.TextBox"
                adapterType="Fiserv.Common.UI.Adapters.DisableViewStateControl" />
            <adapter
                controlType="System.Web.UI.WebControls.CheckBox"
                adapterType="Fiserv.Common.UI.Adapters.DisableViewStateControl" /> 
            <adapter
                controlType="System.Web.UI.WebControls.HiddenField"
                adapterType="Fiserv.Common.UI.Adapters.DisableViewStateControl" /> 
          </controlAdapters>
        </browser>
      </browsers>
      

      通过这种方式,您可以对整个应用程序中的每个单独控件的视图状态进行更精细的控制。在需要控制视图状态的地方,只需在代码中启用它即可。就是这样。

      【讨论】:

        【解决方案5】:

        最简单的解决方案是:

        <%@ Page Language="C#" EnableViewState="true" ViewStateMode="Disabled" %>
        

        以及您想要启用视图状态的任何位置:

        <asp:yourcontrol EnableViewState="true" ViewStateMode="Enabled">
        

        所有学分保留给 Shredder 对此post 的回答

        【讨论】:

        • EnableViewState="true" 不是真正需要的,因为它是默认设置。 ViewStateMode 评估如下。如果“禁用”,则该控件的 EnableViewState 属性将被忽略。上面的代码基本上忽略了页面的 ViewState,并使用控件的现有值。如果您需要以编程方式切换这些行为,这是一个重要的区别
        【解决方案6】:

        您也可以从 BasePage 继承。在 BasePage 上禁用 ViewState。

        /// <summary>
        /// All pages inherit this page
        /// </summary>
        public class BasePage : System.Web.UI.Page {
        
            protected override void OnLoad(EventArgs e) {
                base.OnLoad(e);
            }
        
            public bool ViewStateEnabled {
                get {
                    return Page.EnableViewState;
                }
                set {
                    Page.EnableViewState = value;
                }
            }
        
            public BasePage() {
                // Disable ViewState By Default
                ViewStateEnabled = false;
            }
        }
        

        在您希望启用 ViewState 的每个页面中,您在 Page_Load 中执行以下操作:

        public partial class Products_Default : BasePage {
            protected void Page_Load(object sender, EventArgs e) {
                this.ViewStateEnabled = true;
            }
        }
        

        这应该只为该页面启用 ViewState(假设它在 MasterPage 中为 ON)。注意:您需要在该页面上单独设置每个控件的 ViewState。

        【讨论】:

          【解决方案7】:

          您还可以对内置控件进行子类化,并在您的子类中将 EnableViewState 属性设置为 false。

          【讨论】:

            【解决方案8】:

            我很想知道塞缪尔的方法是否有效。如果您尝试,请发布您的结果。

            我不是说 Samuel 错了,我只是好奇。

            我很好奇的原因是因为视图状态是递归序列化的(正如 Samuel 提到的),如果您有一个启用视图状态的控件是禁用视图状态的控件的子控件,那么子控件将没有视图状态,因为递归序列化将在父级完全跳过它。如果您构建了自己的用户控件自然会包含很多子控件,这将特别令人不安。

            另一种解决方案是使用 Samuel 的实用方法方法,但不是禁用所有内容,而是对没有子项的控件(如 Label、Literal 等)禁用它……或者如果他们确实有子项,如果有子项也可以视图状态已禁用。

            出于我上面所述的原因,您自然希望避免禁用面板和占位符的视图状态。

            编辑:

            Public Shared Sub DisableViewState(ByVal cntrl As Control)
                If TypeOf cntrl Is Label Then
                    cntrl.EnableViewState = False
                ElseIf TypeOf cntrl Is Literal Then
                    cntrl.EnableViewState = False
                ElseIf TypeOf cntrl Is Button Then
                    cntrl.EnableViewState = False
                Else
                    If cntrl.Controls IsNot Nothing Then
                        For Each subControl As Control In cntrl.Controls
                            DisableViewState(subControl)
                        Next
                    End If
                End If
            End Sub
            

            【讨论】:

              猜你喜欢
              • 2017-06-26
              • 2012-09-24
              • 1970-01-01
              • 2010-09-15
              • 1970-01-01
              • 1970-01-01
              • 2010-09-11
              • 1970-01-01
              • 2011-04-27
              相关资源
              最近更新 更多