C# 为少数控件启用 ViewState 并为其他/页面禁用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/186657/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 17:07:39  来源:igfitidea点击:

Enable ViewState for few controls and disable for others/page

c#asp.netviewstate

提问by Zuhaib

When I disable ViewState for the page. It does not allow any other control to use ViewState .. even if I set EnableViewState="true" for that particular control ..

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

is it possible to enable ViewState for a control when ViewState is disabled for the page itself?

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

if not how can disable viewstate for controls on page except for few without specifying EnableViewState="false" explicitly .. typing the same into so many controls is hectic ..

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

采纳答案by Samuel Kim

If you set turn page's ViewState off, then there is no way for you to enable ViewState for specific components. This is because ViewState is serialzed recursively, so when if the Page is not allowing ViewState, it will not serialize the ViewState for any of it's child controls.

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

In answer to your question, if you don't want to explicitly turn ViewState off on individual controls, but want to keep some controls ViewState aware, the best way would be writing a small utility method which turns ViewState off for all controls (using recursion or otherwise). Then enable ViewState for the controls that you would like to enable ViewState for.

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

Alternatively, a middle ground and less forceful way may possible if controls are groups inside other container controls (such as Panel). You can disable ViewState for all controls inside a Panel by disabling ViewState of the Panel.

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

回答by Aaron Powell

Here's some code which expands on @Samuel Kim's concept of having a way to disable ViewState on all but certain controls (btw, it uses .NET 3.5):

这是一些代码扩展了@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;
}

The only thing I'm not 100% sure on (and I don't have my VM running) is whether Page.Controls needs to be cast or not, if so just have this instead:

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

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

The above is only a quick concept of what to do, it doesn't take into account nested controls where you may want 1 with and 1 without ViewState, but it wouldn't be hard to make a recusive function to handle it.

以上只是一个快速操作的概念,它没有考虑嵌套控件,您可能需要 1 和 1 没有 ViewState,但是制作一个递归函数来处理它并不难。

回答by Armstrongest

You could also inherit from a BasePage. On the BasePage disable ViewState.

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

In each page that you want ViewState Enabled, you do the following in Page_Load:

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

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

This should enable ViewState just for that Page (assuming it's ON in the MasterPage). Note: You will need to individually set each control's ViewState on that Page.

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

回答by Adam

I'm curious to see if Samuel's approach works. If you try it please post your result.

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

I'm not saying Samuel's wrong, I'd just be curious.

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

The reason I'm curious is because since viewstate is serialized recursively (as Samuel mentioned) if you had one control with viewstate enabled that was a child of a control with viewstate disabled, then the child control wouldn't have viewstate because the recursive serialization would skip over it entirely at the parent level. This would specifically be troubling if you have built your own user controls that would naturally contain a lot of child controls.

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

Another solution would be to use Samuel's utility method approach but instead of disabling everything, just disable it for controls like Label, Literal, etc that do not have children...or if they do have children it's ok if the children have viewstate disabled.

另一种解决方案是使用 Samuel 的实用方法方法,而不是禁用所有内容,只需禁用它用于没有孩子的控件,如标签、文字等......或者如果他们有孩子,如果孩子禁用视图状态也没关系。

You would naturally want to avoid disabling the viewstate of Panels and Placeholders for the reason I stated above.

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

Edit:

编辑:

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

回答by Mike Cole

You can also subclass the built-in controls, and in your subclass set the EnableViewState property to false.

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

回答by Georgios Politis

If you set turn page's ViewState off, then there is no way for you to enable ViewState for specific components. This is because ViewState is serialzed recursively, so when if the Page is not allowing ViewState, it will not serialize the ViewState for any of it's child controls.it's child controls.

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

With the advent of ASP.NET 4 we have a new property called ViewStateModethat can be used to enable view state for an individual control even if view state is disabled for the page.

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

To make use of this new property you can either create a base page class that sets the ViewStateMode to Disabled or create a PageAdapter that does the same thing. There is no viewStateMode property in the web.config.

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

Here's the code for the page adapter:

这是页面适配器的代码:

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);
        }
    }
}

and here's the code for the browser file:

这是浏览器文件的代码:

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

回答by Amitabh Phogat

With .NET 4.0 you can also define the Control Adapters

使用 .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);
        }
    }
}

In above code, the ViewState mode is disabled when it is inherited. Add the following line in Browser settings file.

在上面的代码中,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>

This way you can have more granular cotnrol over viewstate for each single control throughuout the application. And where you need control to have viewstate just enable it in code. That's it.

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

回答by BornToCode

The simplest solution is:

最简单的解决方案是:

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

and wherever you want to enable viewstate:

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

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

All credits reserved to Shredder's answer on this post

所有学分保留给 Shredder 对这篇文章的回答