问题
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 ..
is it possible to enable ViewState for a control when ViewState is disabled for the page itself?
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 ..
回答1:
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.
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.
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.
回答2:
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.
With the advent of ASP.NET 4 we have a new property called ViewStateMode that can be used to enable view state for an individual control even if view state is disabled for the page.
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.
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>
回答3:
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):
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:
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.
回答4:
With .NET 4.0 you can also define the Control Adapters
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.
<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.
回答5:
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
回答6:
You could also inherit from a BasePage. On the BasePage disable 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:
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.
回答7:
You can also subclass the built-in controls, and in your subclass set the EnableViewState property to false.
回答8:
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.
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.
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
来源:https://stackoverflow.com/questions/186657/enable-viewstate-for-few-controls-and-disable-for-others-page