Custom server controls (control state and events)

Source: Internet
Author: User

Transferred from: http://www.cnblogs.com/SkySoot/archive/2012/12/04/2801424.html

ASP. NET uses Web controls to create an object-oriented abstraction layer above the underlying details of HTTP and HTML. The two foundations of this abstraction are the view state (the mechanism of saving information between multiple requests) and the callback (a technique that enables a page to return a collection of form data to the same URL).

View state

The control needs to save state information, just as the Web page does. All controls provide the ViewState property to allow you to access information, just as you do with a Web page. After a callback, you need to use the ViewState collection to recover the private information.

A common design pattern for Web controls is to access the ViewState collection during property procedures.

In the case of Linkwebcontrol as we mentioned earlier, the control does not use view state, and if it is programmed to change its Text and HyperLink properties, those modifications will be lost during subsequent callbacks . (Note that the style attributes are different and they are automatically saved in view state. )

In order to modify this control to use the attempted state, the following overrides these two properties:

public string Text
{
    get {return (string) viewstate["Text"];}
    set {viewstate["Text"] = value;}
}
public string HyperLink
{
    get {return (string) viewstate["HyperLink"];}
    Set
    {
        if (value. IndexOf ("http://") = =-1)
        {
            throw new ApplicationException ("Specify HTTP as the Protocol");
        }
        Else
        {
            viewstate["HyperLink"] = value;
        }
    }
}
protected override void OnInit (EventArgs e)
{
    Base. OnInit (e);
    if (viewstate["HyperLink"] = = null)
        viewstate["HyperLink"] = "http://www.google.com";
    if (viewstate["Text"] = = null)
        viewstate["Text"] = "click to search";
}

The Linkwebcontrol control can now use the ViewState view state, and the properties that are modified programmatically are not lost in subsequent callbacks.

When the control is initialized, you can request the page to encrypt the view state information by calling the Page.registerrequiresviewstateencryption () method, which is useful when you need to save sensitive information:

protected override void OnInit (EventArgs e)
{
    Base. OnInit (e);
    Page.registerrequiresviewstateencryption ();
    ......
}

It is important to note that the ViewState property of the control is completely separate from the ViewState property of the page. In other words, the ViewState of the two are non-interfering.

The view state in the control is easy to use, but there are a number of issues to consider:

    • do not save large objects in view state . For example, ASP. NET controls that support data binding do not save the DataSource property in ViewState. The data is stored in memory until the DataBind () method is called. You have to rebind the data control after each callback. While this is a bit clumsy in programming, it makes sure that the Web page doesn't get overly bloated.
    • It is subject to the limitations of the pages that contain it . If the page sets the control's EnableViewState to false, the control view state information is lost after each postback. If you have important information to make sure that the control works correctly, you should keep it in the control state information (the control state information is described below).
    • you can't assume that the data is in ViewState . If you try to read an item that does not exist, you will get an exception. You need to check whether the item is a null value in the Onit () method or in the constructor of the custom control, or set the default view state information. (The Linkwebcontrol control does not get a null reference because it uses Onit () to set the initial view-state information)

Note 1

even if the EnableViewState property is set to the False,viewstate collection, it will work correctly. The only difference is that once the control is processed and the page is rendered, the information you set in the collection is discarded.

NOTE 2

Although the WebControl class provides the ViewState property, it does not provide properties such as Cache, Session, application, and so on. But if you need these objects to access the data, you can access the properties by using the static HttpContext.Current property.

Occasionally, you will need more flexibility to customize how the view state information is stored. You can do this by overwriting LoadViewState () and SaveViewState ().

    • SaveViewState () is always called before the control is rendered to HTML, which returns a single Serializable object that is stored in the view state.
    • LoadViewState () is called when the control is created in subsequent postbacks. It takes a parameter to save the object and uses this object to configure the control's properties.

There is no need to overwrite these methods in a simple control, but sometimes it is useful to overwrite them.

When you develop a more compact way to hold multiple information in a single object in view state, when you derive a new control from an existing control, and you want to prevent it from saving its state, you need to override both methods when you manage how to save the state of the inline child control for a complex control.

control state

The control state is used to store the data that the control is using. Technically, the control state works in the same way as the view state. The control state holds those serializable information that is crammed into a hidden field when the page is rendered.

In fact, ASP. NET puts the view state information and control state information in the same hidden field.

Control state is not affected by the EnableViewState property setting, even if false, the control can still access information from the control state.

Because control state cannot be disabled, you should carefully limit the amount of information that is allowed to be saved. Typically, only critical information, such as the index of the current page or the key value of the data, is limited. to use control state, you must start with overriding OnInit () and call Page.registerrequirescontrolstate () to indicate that your control needs to access the state of the control.

protected override void OnInit (EventArgs e)
{
    Base. OnInit (e);
    Page.registerrequirescontrolstate (this);
}

Unlike view state, you cannot directly access control state through a collection (this setting is disgusting, probably because you don't want developers to abuse the state of the control). You must overwrite the two methods SaveControlState () and LoadControlState () again. These methods use a slightly unusual pattern. The basic idea is that you want to get any control state that is serialized by the base class and merge the control state from the base class with the object that contains your new serializable object, implemented by the System.Web.Pair class:

String Somedata;
protected override Object SaveControlState ()
{
    Get the state from the base class.
    Object basestate = base. SaveControlState ();
    
    and return final object.
    return new Pair (Basestate, somedata);
}

This method only allows you to store a single object. If you need to store a lot of information, consider using a custom class that encapsulates all the information and make sure it contains the Serializable property .

You can also create a number of Pair objects:

String StringData;
int intdata;
protected override Object SaveControlState ()
{
    Object basestate = base. SaveControlState ();
    Pair Pair1 = new pair (StringData, intdata);
    Pair Pair2 = new pair (basestate, PAIR1);
    return PAIR2;
}

In LoadControlState (), you pass in the control state of the base class and cast the part of the Pair object to the appropriate type:

protected override void LoadControlState (object savedstate)
{
    Pair P = savedstate as Pair;
    if (P! = null)
    {
        Give the base class it state
        Base. LoadControlState (P.first);
        Now you can process the state of you saved
        Pair Pair1 = P.second as Pair;
        StringData = (string) pair1. First;
        Intdata = (int) pair1. Second;
    }
}

Callback Data and Change events

View state and control state can help keep track of what is in the control, but it is not enough for input controls. This is because the input controls allow users to change their data. For example, consider a text box in a form that represents a <input> label. When the page callback occurs, the data in the,<input> tag is part of the control collection. The TextBox control needs to get this information and update its state accordingly.

In order to process the data that is transferred to the page in a custom control, you need to implement IPostBackDataHandler excuses. By implementing this interface, you indicate to ASP that when a callback occurs, the control needs an opportunity to check the postback data, and your control will get the chance, regardless of which control actually triggers the callback.

The IPostBackDataHandler defines two methods:

    • LoadPostData(): When a page is returned, ASP. NET calls this method before any control events are fired. This allows you to check the returned data and update the state of the control accordingly . However, you should not fire the Change event at this time because other controls are not updated.
    • raisepostdatachangedevent(): after all the input controls on the page have been initialized, if necessary, ASP. NET calls this method to give you a chance to fire the change event.

The best way to understand this principle is through a simple example.

The next control mimics a basic TextBox control. Here is a basic definition of the control:

public class Customtextbox:webcontrol,ipostbackdatahandler
{
    The constructor is initialized to an empty string, and the base tag is set to <input>
    Public Customtextbox ()
        : Base (Htmltextwritertag.input)
    {
        Text = "";
    }
    This control only needs a property Text, the value is saved in the view state
    public string Text
    {
        get {return (string) viewstate["Text"];}
        set {viewstate["Text"] = value;}
    }
    Add the attribute type and value to the <input> tag and you'll be able to handle everything.
    You must use the name attribute to add UniqueID to the control, and ASP. NET to compare this string with the postback data
    If you do not add this UniqueID, the LoadPostData () method will not be called!
    protected override void AddAttributesToRender (HtmlTextWriter writer)
    {
        Writer. AddAttribute (Htmltextwriterattribute.type, "text");
        Writer. AddAttribute (Htmltextwriterattribute.value, Text);
        Writer. AddAttribute ("name", this.) UniqueID);
        Base. AddAttributesToRender (writer);
    }
    Parameter one: The key value of the current control data
    Parameter two: A collection of values that are uploaded back to the page
    public bool LoadPostData (string postdatakey, System.Collections.Specialized.NameValueCollection postcollection)
    {
        Get the posted value and the most recent view state value.
        String postedvalue = Postcollection[postdatakey];
        string viewstatevalue = Text;
        If the value changed, then reset the value of the Text property
        and return true so the raisedatachangedevent would be fired.
        if (viewstatevalue! = postedvalue)
        {
            Text = Postedvalue;
            return true;
        }
        Else
        {
            return false;
        }
    }
    public void RaisePostDataChangedEvent ()
    {
        throw new NotImplementedException ();
    }
}

the task of raisepostdatachangedevent () is relatively simple, which is to excite events. However, most ASP. NET controls use a different layer, through which the RaisePostDataChangedEvent () method calls the OnXXX () method to raise an event. This layer allows other developers to derive a new control from your control and change the behavior of the control by overriding the OnXXX () method.

public event EventHandler TextChanged;
public void RaisePostDataChangedEvent ()
{
    Call the method to raise the Change event
    OnTextChanged (New EventArgs ());
}
public virtual void ontextchanged (EventArgs e)
{
    Check for at least one listener, and then raise the event.
    if (TextChanged! = null)
    {
        TextChanged (this, e);
    }
}

Triggering callbacks

By implementing the IPostBackDataHandler interface, you are able to participate in each callback activity and read the callback data for your control.

But what if you want to trigger a callback?

The simplest example is the button control, which is the HTML form standard and the Submit button always callbacks the page, but many other rich controls, such as the Calendar and the GridView, allow you to trigger a callback by clicking on an element in the rendered HTML or a link.

This can be provided through another asp: the JavaScript function _dopostback (). The _dopostback () function accepts 2 parameters: the name of the control that triggered the callback and a string representing the additional postback data.

ASP. NET provides the Page.ClientScript.GetPostBackEventReference () method to simplify access to the _dopostback () function. This method creates a reference to the client's _dopostback () function so that you can render the reference to the control. In general, you will place this function reference in the OnClick attribute of the control's HTML element. Thus, when the HTML element is clicked, the _dopostback () function is triggered.

Below, create a simple example to understand the callback mechanism. This example shows an image that can be clicked, and clicking on it will return the page without any additional data:

public string ImageUrl
{
    get {return (string) viewstate["ImageUrl"];}
    set {viewstate["ImageUrl"] = value;}
}
Public Customimagebutton ()
    : Base (HTMLTEXTWRITERTAG.IMG)
{
    IMAGEURL = "";
}

The only job you need to customize is to add some features to be presented, including a unique control name, URL to the image, and an OnClick attribute that associates the image with the _dopostback () function:

protected override void AddAttributesToRender (HtmlTextWriter writer)
{
    Writer. AddAttribute ("name", this.) UniqueID);
    Writer. AddAttribute ("src", this.) IMAGEURL);
    
        Page.ClientScript.GetPostBackEventReference (this,string. Empty));            
}

This is sufficient for triggering callbacks, but it takes a few more steps to participate in the callback and fire an event. This time, you need to implement the IPostBackEventHandler interface to implement its definition of raisepostbackevent ():

public class Customimagebutton:webcontrol,ipostbackeventhandler
{ ... }

when the page is returned, ASP. NET determines which control triggers the callback (by looking at the UniqueID of each control), and if that control implements the IPostBackEventHandler event handler, ASP. NET is called with the event data RaisePostBackEvent () method. At this point, all the controls on the page are initialized, and it is safe to trigger an event :

public event EventHandler imageclicked;
public void RaisePostBackEvent (String eventargument)
{
    onimageclicked (New EventArgs ());
}
public virtual void onimageclicked (EventArgs e)
{
    if (imageclicked! = null)
    {
        Imageclicked (this, e);
    }
}

Create a test page with the following effect:

The control itself does not provide functionality that is not available for existing ASP. For example, ImageButton. However, this is a good starting point for creating some more useful controls.

In addition, many times do not need to return the entire page, you can use callbacks to retrieve some specific information from the server side.

Custom server controls (control state and events)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.