对少数控件启用ViewState,对其他控件禁用/page

本文关键字:控件 page 其他 ViewState 启用 | 更新日期: 2023-09-27 17:48:51

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

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

如果不是,如何在不显式指定EnableViewState="false"的情况下禁用页面上控件的视图状态(少数控件除外)。。在这么多控件中键入相同的内容是很忙的。。

对少数控件启用ViewState,对其他控件禁用/page

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

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

或者,如果控件是其他容器控件(如Panel)内的组,则可以采用中间立场和不那么有力的方式。您可以通过禁用面板的ViewState来禁用面板内所有控件的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>

以下是一些代码,它扩展了@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%确定的事情(我没有运行我的VM)是Page.Controls是否需要强制转换,如果需要的话,就改为:

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

上面只是一个快速的概念,它没有考虑嵌套控件,其中你可能想要1带ViewState和1不带ViewState,但制作一个回避函数来处理它并不困难。

使用.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>

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

最简单的解决方案是:

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

以及任何您想启用viewstate的地方:

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

Shredder在这篇文章中的回答保留了所有学分。

您也可以从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。

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

我很好奇Samuel的方法是否有效。如果你尝试了,请公布你的结果。

我并不是说塞缪尔错了,我只是好奇而已。

我很好奇的原因是,由于viewstate是递归序列化的(正如Samuel所提到的),如果你有一个启用了viewstate的控件,它是禁用了viewstate控件的子控件,那么子控件就不会有viewstate,因为递归序列化会在父级完全跳过它。如果您已经构建了自己的用户控件,其中自然包含许多子控件,那么这将特别令人不安。

另一个解决方案是使用Samuel的实用程序方法,但不是禁用所有内容,而是对没有子项的控件(如Label、Literal等)禁用它。。。或者如果他们确实有孩子,如果孩子的viewstate被禁用也没关系。

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

编辑:

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