Update UpdatePanel using JavaScript (1)

Source: Internet
Author: User

As we all know, UpdatePanel is updated through Trigger. The control set as a Trigger will be intercepted by the client after the PostBack, And the content is sent using the XMLHttpRequest object. Then, the server side is used by ScriptManager to change the output of the Page object, the last part is refreshed. However, sometimes we may need JavaScript to refresh UpdatePanel, which is inconvenient.

Of course, we have a Workaround method, that is, using JavaScript to simulate Button clicking. We usually set a button as a Trigger of an UpdatePanel, and then simulate it on the client. I will mention it later. In fact, this is a bad practice and is not necessary ), update UpdatePanel. However, this approach is too troublesome and not elegant.

Now let's write a component to solve this problem. The component name is tentatively called JavaScriptUpdater.

First, set a requirement.

Our goal is to generate a JavaScript proxy on the client, provide a method, and refresh the page after calling it. If the UpdateMode of an UpdatePanel is Always, it will be updated. If you want to update UpdatePanel whose UpdateMode is Conditional, you need to write tags on the page to set which UpdatePanel will be updated. We need to minimize programming effort as much as possible.

We should consider how to use it first. The JavaScriptUpdater we wrote can be used in the page as follows:

JavaScriptUpdater usage:

<helper:JavaScriptUpdater runat="server" ID="Updater" MethodName="Refresh"    ResolveUpdatePanel="OnResolveUpdatePanel" Enabled="True">    <UpdatePanels>        <helper:UpdatePanel UpdatePanelID="UpdatePanel1" />        ...    </UpdatePanels></helper:JavaScriptUpdater>

JavaScriptUpdater has a simple attribute MethodName, indicating the name of the proxy method generated on the client. In the preceding example, this attribute is Refresh, indicating that the UpdatePanels. Refresh () method is called to update the UpdatePanel. UpdatePanels is a set attribute. You can specify which UpdateMode is the UpdatePanel of Conditional for updates. If an UpdatePanelID is not found, the ResolveUpdatePanel event is called to allow you to specify an UpdatePanel. There is also an Enabled attribute to control whether the JavaScriptUpdater takes effect.

Multiple JavaScriptUpdater can be placed on a page to generate multiple JavaScript proxy methods. This setting should be enough.

Implement JavaScriptUpdater

Naturally, we first define the simplest two classes: UpdatePanelHelper. UpdatePanel class and ResolveUpdatePanelEventArgs class. Because it is really simple, you can directly paste the Code:

UpdatePanel class:

namespace UpdatePanelHelper{    public class UpdatePanel    {        private string _UpdatePanelID;        public string UpdatePanelID        {            get { return _UpdatePanelID; }            set { _UpdatePanelID = value; }        }    }}

ResolveUpdatePanelEventArgs class:

namespace UpdatePanelHelper{    public class ResolveUpdatePanelEventArgs : EventArgs    {        private string _ID = null;        public string ID        {            get { return _ID; }        }        private System.Web.UI.UpdatePanel _UpdatePanel = null;        public System.Web.UI.UpdatePanel UpdatePanel        {            get { return _UpdatePanel; }            set { _UpdatePanel = value; }        }        public ResolveUpdatePanelEventArgs(string id)        {            this._ID = id;        }    }}

Then begin to consider writing the most critical JavaScriptUpdater class. First, define its simple framework as follows:

The overall framework and attribute definition of the JavaScriptUpdater control:

namespace UpdatePanelHelper{    [PersistChildren(false)]    [ParseChildren(true)]    [NonVisualControl]    public class JavaScriptUpdater : Control    {        private bool initialized = false;        private bool _Enabled = true;        public bool Enabled        {            get            {                return this._Enabled;            }            set            {                if (this.initialized)                {                    throw new InvalidOperationException(                        "Cannot set the property after initialized.");                }                this._Enabled = value;            }        }        private string _MethodName;        public string MethodName        {            get            {                return this._MethodName;            }            set            {                if (this.initialized)                {                    throw new InvalidOperationException(                        "Cannot set the property after initialized.");                }                this._MethodName = value;            }        }        public event EventHandler
 
   ResolveUpdatePanel;                private List
  
    _UpdatePanels = new List
   
    ();        [PersistenceMode(PersistenceMode.InnerProperty)]        public List
    
      UpdatePanels        {            get            {                return _UpdatePanels;            }        }        ...    }}
    
   
  
 

We use an initialized variable to ensure that the Enabled or MethodName attribute can only be modified during page Init. Since the control operates in multiple lifecycles, if you do not impose such restrictions, the control will become cumbersome and error-prone. The following code shows that the initialized variable is set to true in response to the InitComplete event on the page.

Here we implement the UpdatePanel update method in JavaScript, which is similar to the traditional method, but here we will add buttons dynamically and use LinkButton here. We will respond to the Load event of the Page Object and add the LinkButton that serves as the Trigger. As follows:

Dynamically Add a LinkButton:

private string clientButtonId = null;protected override void OnInit(EventArgs e){    base.OnInit(e);    this.Page.InitComplete += new EventHandler(Page_InitComplete);}private void Page_InitComplete(object sender, EventArgs e){    this.initialized = true;    if (this.Enabled)    {        this.Page.Load += new EventHandler(Page_Load);        this.Page.PreRenderComplete += new EventHandler(Page_PreRenderComplete);    }}private void Page_Load(object sender, EventArgs e){    LinkButton button = new LinkButton();    button.Text = "Update";    button.ID = this.ID + "Button";    button.Style[HtmlTextWriterStyle.Display] = "none";    button.Click += new EventHandler(OnTrigger);    this.Page.Form.Controls.Add(button);    this.clientButtonId = button.UniqueID;    ScriptManager.GetCurrent(this.Page).RegisterAsyncPostBackControl(button);}

In the Page_InitComplete event on the page, if the Enabled attribute is true, the Enabled attribute cannot be modified.) If the Enabled attribute is true, the system responds to the Load event of the page to dynamically Add a LinkButton. Please note that we will not set its Visible attribute to False, otherwise its HTML will not appear on the page. We should set the display of the Style to none, so that it can appear in the page structure or not. After this LinkButton is added, its ClientID will be retained and the ScriptManager of the current page will be located. Call the RegisterAsyncPostBackControl method to register this LinkButton as the control for Asynchronously refreshing the page.

In the past, I used a Button as a Trigger to Write examples to others, and then clicked it on the client using JavaScript. This is actually not very reasonable. It is a good practice to use LinkButton. To explain the cause of this problem, we need to take a look at the HTML elements generated by LinkButton on the page. Obviously, this is <a/>, as follows:

HTML generated by LinkButton:

<a id="UpdaterButton" href="javascript:__doPostBack('UpdaterButton','')">Update</a>

Note its href, which indicates that clicking this element will execute this JavaScript code. Found? Why do we need to simulate the click of an element? We just need to call the _ doPostBack function? Cool! So now we can easily figure out the Script to be registered in response to the PreRenderComplete event on the page. As follows:

Register the script in the PreRenderComplete event:

private const string BasicScripts = @"if (!window.UpdatePanels) window.UpdatePanels = {};UpdatePanels._createUpdateMethod = function(btnId){    return function()    {        __doPostBack(btnId, '');    }}";private const string RegisterMethodTemplate =     "\nUpdatePanels['{0}'] = UpdatePanels._createUpdateMethod('{1}');";    private void Page_PreRenderComplete(object sender, EventArgs e){    this.Page.ClientScript.RegisterClientScriptBlock(        this.GetType(),        "BasicScripts",        JavaScriptUpdater.BasicScripts,        true);    this.Page.ClientScript.RegisterClientScriptBlock(        this.GetType(),        this.clientButtonId,        String.Format(JavaScriptUpdater.RegisterMethodTemplate,             this.MethodName, this.clientButtonId),        true);}

First, some basic scripts will be registered. We will use the same Type and Key parameters to ensure that this code will only be registered once. When registering a script for each proxy method, the clientButtonId of the script is used as the key to ensure that each script is successfully registered. By the way, we directly use the ClientScriptManager of Page to register the script. This ensures that the script will not be sent to the client when UpdatePanel is asynchronously updated.

Some may wonder why we need to register the script in the PreRenderComplete event on the page? Can I register a Load event on the page? The answer is, because ScriptManager is also the BASIC script for registering ASP. net ajax at this time, we are doing this to ensure that the registered script appears after the ASP. net ajax script.

Oh, so it turns out ...... Wait, do you notice that our current script is irrelevant to the BASIC script of ASP. net ajax? That's right. In fact, we can use this method to register in the Load event of the page. Now I seem to be just a habit-or for ASP. net ajax: A mode for compiling components-a response to the PreRenderComplete event on the page, used to register the required script.

Most of the work has been completed. We only need to respond to the Click Event of the LinkButton. We need to force update all specified UpdatePanel. The Code is as follows:

Trigger update:

private void OnTrigger(object sender, EventArgs e){    if (this.Enabled)    {        foreach (UpdatePanel panel in this.UpdatePanels)        {            System.Web.UI.UpdatePanel updatePanel =                 this.FindUpdatePanel(panel.UpdatePanelID);            if (updatePanel != null)            {                updatePanel.Update();            }        }    }}private System.Web.UI.UpdatePanel FindUpdatePanel(string id){    System.Web.UI.UpdatePanel result = null;    if (id != null)    {        result = this.NamingContainer.FindControl(id)            as System.Web.UI.UpdatePanel;    }    if (result == null)    {        ResolveUpdatePanelEventArgs e = new ResolveUpdatePanelEventArgs(id);        this.OnResolveUpdatePanel(e);        result = e.UpdatePanel;    }    return result;}private void OnResolveUpdatePanel(ResolveUpdatePanelEventArgs e){    if (this.ResolveUpdatePanel != null)    {        this.ResolveUpdatePanel(this, e);    }}


Related Article

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.