为少数控件启用ViewState,为其他/页面启用禁用

时间:2008-10-09 10:21:32

标签: c# asp.net viewstate

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

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

如果不能如何禁用页面上控件的viewstate除了少数而没有明确指定EnableViewState =“false”...在很多控件中输入相同的东西是忙碌..

8 个答案:

答案 0 :(得分:22)

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

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

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

答案 1 :(得分:6)

  

如果您关闭翻页的ViewState,   然后你无法启用   特定组件的ViewState。   这是因为ViewState是序列化的   递归,所以如果Page是   不允许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>

答案 2 :(得分:2)

这里有一些代码扩展了@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和1没有ViewState,但是要做一个重复函数来处理它并不困难

答案 3 :(得分:2)

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

通过这种方式,您可以在整个应用程序中为每个控件提供更多粒度的cotnrol over viewstate。而且你需要控制才能让viewstate在代码中启用它。就是这样。

答案 4 :(得分:2)

最简单的解决方案是:

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

以及您要启用viewstate的任何位置:

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

Shredder对此post

的回答保留所有信用

答案 5 :(得分:0)

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

答案 6 :(得分:0)

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

我不是说撒母耳错了,我只是好奇。

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

另一个解决方案是使用Samuel的实用方法方法,但不是禁用所有内容,只需禁用它,如Label,Literal等没有孩子的控件......或者如果他们确实有孩子,那么孩子们可以viewstate disabled。

您自然希望避免因上述原因而禁用Panels和Placeholders的视图状态。

编辑:

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

答案 7 :(得分:0)

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

相关问题