对少数控件启用ViewState,对其他控件禁用/page
本文关键字:控件 page 其他 ViewState 启用 | 更新日期: 2023-09-27 17:48:51
当我禁用页面的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序列化任何的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