当我禁用页面的 ViewState 时。它不允许任何其他控件使用 ViewState .. 即使我为该特定控件设置 EnableViewState="true" ..
当为页面本身禁用 ViewState 时,是否可以为控件启用 ViewState?
如果不是,如何禁用页面上控件的视图状态,除了少数没有明确指定 EnableViewState="false" .. 在这么多控件中输入相同内容是忙碌的..
如果您将翻页的 ViewState 设置为关闭,那么您将无法为特定组件启用 ViewState。这是因为 ViewState 是递归序列化的,所以如果 Page 不允许 ViewState,它不会为它的任何子控件序列化 ViewState。
在回答您的问题时,如果您不想在单个控件上显式关闭 ViewState,但希望保持某些控件 ViewState 感知,最好的方法是编写一个小的实用程序方法来关闭所有控件的 ViewState(使用递归或其他)。然后为要为其启用 ViewState 的控件启用 ViewState。
或者,如果控件是其他容器控件(例如 Panel)内的组,则可以采用中间立场和不太有力的方式。您可以通过禁用面板的 ViewState 来禁用面板内所有控件的 ViewState。
如果您将翻页的 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>
这里有一些代码扩展了@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,但是制作一个 recusive 函数来处理它并不难。
使用 .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" %>
以及要启用视图状态的任何位置:
<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。
我很好奇塞缪尔的方法是否有效。如果您尝试,请发布您的结果。
我不是说塞缪尔错了,我只是好奇。
我很好奇的原因是因为视图状态是递归序列化的(如 Samuel 所述),如果您有一个启用了视图状态的控件,它是禁用了视图状态的控件的子控件,那么子控件将没有视图状态,因为递归序列化将在父级完全跳过它。如果您已经构建了自己的用户控件,自然会包含很多子控件,这将特别令人不安。
另一种解决方案是使用 Samuel 的实用方法方法,但不是禁用所有内容,而是禁用它,以便为没有孩子的标签、文字等控件禁用它......或者如果他们确实有孩子,那么如果孩子禁用 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
您还可以子类化内置控件,并在您的子类中将 EnableViewState 属性设置为 false。