Article 3: properties _ Section 1: control property and property persistence; Article 3 controls
I. control attributes
Attribute is the basic syntax of various. net languages. We often say that the control property refers to the property that is modified with public in the control class.
See Lable's Text attributes:
[Bindable(true), DefaultValue(""), Localizable(true), PersistenceMode(PersistenceMode.InnerDefaultProperty), WebCategory("Appearance"), WebSysDescription("Label_Text")]
public virtual string Text
{
get
{
object obj = this.ViewState["Text"];
if (obj != null)
{
return (string)obj;
}
return string.Empty;
}
set
{
if (this.HasControls())
{
this.Controls.Clear();
}
this.ViewState["Text"] = value;
}
}
2. Attribute persistence
What are Lable's Text attributes? Why not encapsulate a string field directly?
Before answering these questions, let's take a look at this experiment.
Note: Lable has a son like this:
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
namespace CustomServerControl
{
public class MemorylessLable : Label
{
public override string Text
{
get;
set;
}
}
}
One day, Lable and his son lined up and stood in the same posture:
<div>
<csc:MemorylessLable ID="MemorylessLable1" Text="MemorylessLable" runat="server">
</csc:MemorylessLable>
<br />
<asp:Button ID="btnMemorylessLable" runat="server" Text="MemorylessLableAdd(?)" OnClick="btnMemorylessLable_Click" />
</div>
<div>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
<br />
<asp:Button ID="btnLabel" runat="server" Text="LabelAdd(?)" OnClick="btnLabel_Click" />
</div>
They are doing the same thing:
protected void btnMemorylessLable_Click(object sender, EventArgs e)
{
MemorylessLable1.Text += "?";
}
protected void btnLabel_Click(object sender, EventArgs e)
{
Label1.Text += "?";
}
But ......
However, it is the result you see. But why?
Let's review the HTTP protocol working mode: HTTP is a stateless disconnected connection mode, that is, the client sends a request to the server, after the server responds, the client information of the request is no longer maintained. By default, multiple requests come from the same client or different clients, and the processing method is no different for the server.
1. View status
Now, we have figured out why the Text attribute in MemorylessLable is not remembered. Back to the beginning of the problem, what did Lable's Text attribute do? What makes him seem to have memories?
The generated HTML contains a hidden form field named "_ VIEWSTATE:
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTEzNjg4MTc2OQ9kFgICAw9kFgICBQ8PFgIeBFRleHQFCkxhYmVsPz8/Pz9kZGTR/AR1D6vaE/KV3PxzwkBnTnXssA==" />
To solve the problem of saving the control status, ASP. NET introduces a feature called ViewState. Controls that need to save the value during page return. You can save the value in the view State, ASP. NET Framework will serialize the view information into a string before rendering the page, and save it to a hidden form field named _ VIEWSTATE on the page (<input type = 'hiddn'/>). In this way, the control state is saved to the client, and the values in the Form field are hidden and submitted back to the server by the Form (Form) when the next page is returned, the server deserializes the value of the hidden _ VIEWSTATE field submitted back to restore the status of each control.
However, you may want to disable the view status. Yes, view status can be disabled. EnableViewState = "false" is added to the <% @ Page %> command at the top of the front-end file ". When will it be disabled? Imagine, for example, a page has a GridView that generates several KB views (the GridView will generate a large number of view status content), and N forms are submitted multiple times. Therefore, the view status of several KB is transmitted between the client and the server, which slows down the response speed of the webpage. Okay. Let's add EnableViewState = "false" to our Demo and take a look.
2. control status
However, some information is crucial to the correct operation of the control. For example, the PageIndex attribute in the GridView we just mentioned. If this attribute is serialized to the view State, when the view State is disabled on the page, the pagination function of the GridView will crash completely. But this is not the case. How does GirdView achieve this? For example, Title: ControlState ).
ASP. NET2.0 and later provide control developers with a mechanism to save control status values more securely than view statuses. The control status is similar to the view status, but it is valid when the user sets EnableViewState = "false.
Lable's grandson:
using System;
using System.Collections.Generic;
using System.Text;
namespace CustomServerControl
{
public class SuperMemoryLable:MemorylessLable
{
protected override void OnInit(EventArgs e)
{
// The page where the notification control is running. register the control as a control in the persistent control state.
Page.RegisterRequiresControlState(this);
base.OnInit(e);
}
// Return the value to be saved to the control status
protected override object SaveControlState()
{
return this.Text;
}
// Parses the deserialized objects from the control status into the status values of the control.
protected override void LoadControlState(object savedState)
{
this.Text = savedState as string;
}
}
}
Lable and Sun Tzu played the game of his son and him:
<div>
<csc:SuperMemoryLable ID="SuperMemoryLable1" runat="server" Text="SuperMemoryLable">
</csc:SuperMemoryLable>
<br />
<asp:Button ID="btnSuperMemoryLable" runat="server" Text="SuperMemoryLableAdd(?)"
OnClick="btnSuperMemoryLable_Click" />
</div>
<div>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
<br />
<asp:Button ID="btnLabel" runat="server" Text="LabelAdd(?)" OnClick="btnLabel_Click" />
</div>
Game upgrade: A glimpse after adding EnableViewState = "false.
Iii. Summary
1. Control Properties refer to the properties modified with public in the control class.
2. There are two ways to achieve property Persistence:
① Serialize the control attributes to the view State;
② Serialize the control attributes to the control status.
When developing a page, EnableViewState = "false" can be used to disable the view State.
3. Three steps to apply the control status:
① Override the OnInit () method. Before calling base. OnInit (), call the Page. RegisterRequiresControlState () method to notify the Page where the control is running, and provide the control status function for it;
② Override the SaveControlState () method to provide the values that need to be saved to the control state;
③ Rewrite the LoadControlState () method to parse the deserialized objects from the control state into various State values of the control.
Appendix: The PageIndex attribute of the GridView is persisted through the control state:
Step 1:
protected internal override void OnInit(EventArgs e)
{
base.OnInit(e);
if (this.Page != null)
{
if (this.DataKeyNames.Length > 0 && !this.AutoGenerateColumns)
{
this.Page.RegisterRequiresViewStateEncryption();
}
// The page on which the notification control is running. You need to provide the control status function for the notification control.
this.Page.RegisterRequiresControlState(this);
}
}
Step 2:
protected internal override object SaveControlState()
{
object obj = base.SaveControlState();
if (obj != null || this._pageIndex != 0 || this._editIndex != -1 || this._selectedIndex != -1 ||
(this._sortExpression != null && this._sortExpression.Length != 0) || (this._sortDirection != SortDirection.Ascending ||
(this._dataKeyNames != null && this._dataKeyNames.Length != 0)) ||
(this._dataKeysArrayList != null && this._dataKeysArrayList.Count > 0) || this._pageCount != -1)
{
return new object[]
{
obj,
(this._editIndex == -1) ? null : this._editIndex,
(This. _ pageIndex = 0 )? Null: this. _ pageIndex, // The value of the PageIndex attribute and other values that need to be saved to the control state to form a complex object (object [])
(this._selectedIndex == -1) ? null : this._selectedIndex,
(this._sortExpression == null || this._sortExpression.Length == 0) ? null : this._sortExpression,
(this._sortDirection == SortDirection.Ascending) ? null : ((int)this._sortDirection),
(this._dataKeyNames == null || this._dataKeyNames.Length == 0) ? null : this._dataKeyNames,
this.SaveDataKeysState(),
this._pageCount,
(this._persistedDataKey == null) ? null : ((IStateManager)this._persistedDataKey).SaveViewState(),
(this._clientIDRowSuffix == null || this._clientIDRowSuffix.Length == 0) ? null : this._clientIDRowSuffix,
this.SaveClientIDRowSuffixDataKeysState()
};
}
return true;
}
Step 3:
protected internal override void LoadControlState(object savedState)
{
this._editIndex = -1;
this._pageIndex = 0;
this._selectedIndex = -1;
this._sortExpression = string.Empty;
this._sortDirection = SortDirection.Ascending;
this._dataKeyNames = new string[0];
this._pageCount = -1;
object[] array = savedState as object[];
if (array != null)
{
base.LoadControlState(array[0]);
if (array[1] != null)
{
this._editIndex = (int)array[1];
}
if (array[2] != null)
{
This. _ pageIndex = (int) array [2]; // parses the status value of the PageIndex attribute from the deserialized object in the control status
}
if (array[3] != null)
{
this._selectedIndex = (int)array[3];
}
if (array[4] != null)
{
this._sortExpression = (string)array[4];
}
if (array[5] != null)
{
this._sortDirection = (SortDirection)array[5];
}
if (array[6] != null)
{
this._dataKeyNames = (string[])array[6];
}
if (array[7] != null)
{
this.LoadDataKeysState(array[7]);
}
if (array[8] != null)
{
this._pageCount = (int)array[8];
}
if (array[9] != null && this._dataKeyNames != null && this._dataKeyNames.Length > 0)
{
this._persistedDataKey = new DataKey(new OrderedDictionary(this._dataKeyNames.Length), this._dataKeyNames);
((IStateManager)this._persistedDataKey).LoadViewState(array[9]);
}
if (array[10] != null)
{
this._clientIDRowSuffix = (string[])array[10];
}
if (array[11] != null)
{
this.LoadClientIDRowSuffixDataKeysState(array[11]);
return;
}
}
else
{
base.LoadControlState(null);
}
}