Generating Client-Side Script for Postback


We'll now return to our discussion of postback and show how to implement a control that causes postback via client-side script. Only two HTML elements, <input type="button"> and <input type="image"> , are intrinsically capable of posting a form back to the server. However, other form elements (such as a link or a text box) can be made to cause postback by submitting the form via a client-side event handler. The page framework makes it easy for you to implement such postback functionality in a form control. To see how this works, we'll create a SimpleLinkButton control (similar to the ASP.NET LinkButton ) that renders a hyperlink that, when clicked, posts the form back to the server.

Listing 9-5 shows the code for the SimpleLinkButton control. SimpleLinkButton renders a hyperlink instead of a button, but the code is similar to that of the SimpleButton control shown in Listing 9-3. As with the SimpleButton control, SimpleLinkButton implements IPostBackEventHandler and raises a Click event on the server in response to a client-side submit event. The main difference between the two controls is that SimpleLinkButton generates client-side script to cause postback. The code that provides this functionality is highlighted in Listing 9-5. Let's look at the code first and then discuss what it does. You will also see that SimpleLinkButton uses the optimized event property construct that we described in the previous section.

Listing 9-5 SimpleLinkButton.cs
 usingSystem; usingSystem.ComponentModel; usingSystem.Web.UI; usingSystem.Web.UI.WebControls; namespaceMSPress.ServerControls{ [DefaultEvent("Click"), DefaultProperty("Text")] publicclassSimpleLinkButton:WebControl,IPostBackEventHandler{ privatestaticreadonlyobjectEventClick=newobject(); [Bindable(true), Category("Behavior"), DefaultValue(""), Description("Thetexttodisplayonthelink")] publicvirtualstringText{ get{ strings=(string)ViewState["Text"]; return((s==null)?String.Empty:s); } set{ ViewState["Text"]=value; } } protectedoverrideHtmlTextWriterTagTagKey{ get{ returnHtmlTextWriterTag.A; } } [Category("Action"),Description("Raised when the hyperlink is clicked")] publiceventEventHandlerClick{ add{ Events.AddHandler(EventClick,value); } remove{ Events.RemoveHandler(EventClick,value); } } 
 //MethodofIPostBackEventHandlerthatraisespostbackevents. voidIPostBackEventHandler.RaisePostBackEvent(stringeventArgument){ OnClick(EventArgs.Empty); } protectedoverridevoidAddAttributesToRender(HtmlTextWriterwriter){ base.AddAttributesToRender(writer);  writer.AddAttribute(HtmlTextWriterAttribute.Href, Page.GetPostBackClientHyperlink(this,String.Empty));  } //RetrievesthedelegatefortheClickeventand //invokesthehandlersregisteredwiththedelegate. protectedvirtualvoidOnClick(EventArgse){ EventHandlerclickHandler= (EventHandler)Events[EventClick]; if(clickHandler!=null){ clickHandler(this,e); } } protectedoverridevoidRender(HtmlTextWriterwriter){ //Makesurethiscontrolisnestedinaform. if(Page!=null){ Page.VerifyRenderingInServerForm(this); } base.Render(writer); } protectedoverridevoidRenderContents(HtmlTextWriterwriter){ writer.Write(Text); } } } 

The key feature of the SimpleLinkButton control is the call to the GetPostBackClientHyperlink method of its containing page. This method of the Page class generates client-side script that causes postback from the hyperlink. The more general method that generates client-side script is GetPostBackEventReference . We'll describe GetPostBackEventReference later in this section. To see what the GetPostBackClientHyperlink method does, use the SimpleLinkButton control on a page and view the page in a browser. Listing 9-6 provides a sample page.

Listing 9-6 SimpleLinkButtonTest.aspx
 <%@PageLanguage="C#"%> <%@RegisterTagPrefix="msp"Namespace="MSPress.ServerControls" Assembly="MSPress.ServerControls"%> <html> <head> <scriptrunat="server"> voidsimpleLinkButton1_Click(objectsender,EventArgse){ label1.Text="Youclickedthebutton."; } </script> </head> <body> <formrunat="server"> Clickthelinktoraiseitsserver-sideClickevent. <br> <msp:SimpleLinkButtonText="ClickMe"runat="server" OnClick="simpleLinkButton1_Click"id="simpleLinkButton1"/> <br> <asp:LabelFont-Size="10pt"Font-Bold="true"id="label1" runat="server"/> </form> </body> </html> 

If you view the source for the page, you will see HTML such as the following, which is generated by SimpleLinkButton :

 <aid="simpleLinkButton1" href="javascript:__doPostBack('simpleLinkButton1','')">ClickMe</a> 

At the bottom of the page, you will see two hidden fields and a script block containing a JavaScript function that causes postback:

 <inputtype="hidden"name="__EVENTTARGET"value=""/> <inputtype="hidden"name="__EVENTARGUMENT"value=""/> <scriptlanguage="javascript"> <!-- function__doPostBack(eventTarget,eventArgument){ vartheform=document._ctl0; theform.__EVENTTARGET.value=eventTarget; theform.__EVENTARGUMENT.value=eventArgument; theform.submit(); } //--> </script> 

Let's examine how these elements are rendered. If you look at the Add ­AttributesToRender method in SimpleLinkButton (shown in Listing 9-5), you will see the following call:

 writer.AddAttribute(HtmlTextWriterAttribute.Href,  Page.GetPostBackClientHyperlink(this,String.Empty)  ); 

The GetPostBackClientHyperlink method does two things. First, GetPostBackClientHyperlink returns the string "javascript:__doPost ­Back('simpleLink ­Button1','')" that contains a call to the __ doPostBack JavaScript function generated by the page framework. You can assign this string to the href attribute of the HTML <a> tag. The values that GetPostBackClientHyperlink passes in as the parameters of the __ doPostBack event handler are: the UniqueID of the control and an optional string argument that is used when your control renders multiple postback elements. We did not use the second argument in SimpleLinkButton , because it renders only one HTML element. We will use it in the next section in the NavButtons control, which renders multiple elements that cause postback.

Second, GetPostBackClientHyperlink tells the page to render two hidden fields ( __EVENTTARGET and __EVENTARGUMENT ) and a JavaScript function that causes postback (__ doPostBack ). The page makes sure that the hidden elements and the script function are rendered only once on the page, even if it contains multiple controls that cause postback.

When the user clicks the hyperlink in the browser, the JavaScript function __ doPostBack is invoked. On the client, this function assigns the UniqueID of the control to the value of the __EVENTTARGET hidden field, assigns the event argument (if any) to the __EVENTARGUMENT hidden field, and posts the form. On the server, the page reads the __EVENTTARGET variable in the form post data and invokes the RaisePostBackEvent method of the control whose UniqueID matches the value of the __EVENTTARGET variable. In addition, the page passes the value of the __EVENTARGUMENT variable in the form post data as the argument to the RaisePostBackEvent method.

When your control renders script for postback, you do not have to render the UniqueID of your control as the name attribute on the HTML tag because the __EVENTTARGET hidden field contains the UniqueID of your control. This is different from the SimpleButton control (shown in Listing 9-3), which does not use client-side script for postback and renders the UniqueID as the name attribute on the HTML tag.

Under the hood, GetPostBackClientHyperlink invokes a more general method that generates client-side script: GetPostBackEventReference . GetPostBackClientHyperlink prepends the string "javascript:" to the string returned by GetPostBackEventReference . This prefix is needed to invoke the event handler on the client when a user clicks the hyperlink. When you render a form element other than a hyperlink, invoke the method GetPostBackEventReference and assign the returned string to an HTML attribute (such as onchange or onclick ) on the tag of the HTML element that your control renders. The process of script generation and hidden variables is identical to that described earlier for GetPostBackClientHyperlink . Next we'll provide an example of a control that uses GetPostBackEventReference.

Rendering Multiple Elements That Use Client Script for Postback ” The NavButtons Example

We'll now create a NavButtons control that renders Previous/Next navigational buttons that cause postback. NavButtons renders client-side script that writes a value corresponding to the button clicked by the user into the __EVENT ­ARGUMENT hidden field, which we described in the previous section. The page passes this argument into the RaisePostBackEvent method of the control, and the control can use the argument to determine which element caused postback and accordingly raise the appropriate event. Listing 9-7 contains the code for the NavButtons control.

Listing 9-7 NavButtons.cs
 usingSystem; usingSystem.ComponentModel; usingSystem.Web.UI; usingSystem.Web.UI.WebControls; namespaceMSPress.ServerControls{ [DefaultEvent("ClickNext"), DefaultProperty("NextText")] publicclassNavButtons:WebControl,IPostBackEventHandler{ privatestaticreadonlyobjectEventClickNext=newobject(); privatestaticreadonlyobjectEventClickPrevious= newobject(); [Bindable(true), Category("Behavior"), DefaultValue(""), Description("ThetexttodisplayontheNextbutton")] publicvirtualstringNextText{ get{ strings=(string)ViewState["NextText"]; 
 return((s==null)?String.Empty:s); } set{ ViewState["NextText"]=value; } } [Bindable(true), Category("Behavior"), DefaultValue(""), Description("ThetexttodisplayonthePreviousbutton")] publicvirtualstringPreviousText{ get{ strings=(string)ViewState["PreviousText"]; return((s==null)?String.Empty:s); } set{ ViewState["PreviousText"]=value; } } [Category("Action"), Description("RaisedwhentheNextbuttonisclicked")] publiceventEventHandlerClickNext{ add{ Events.AddHandler(EventClickNext,value); } remove{ Events.RemoveHandler(EventClickNext,value); } } [Category("Action"), Description("RaisedwhenthePreviousbuttonisclicked")] publiceventEventHandlerClickPrevious{ add{ Events.AddHandler(EventClickPrevious,value); } remove{ Events.RemoveHandler(EventClickPrevious,value); } } //InvokesdelegatesregisteredwiththeClickNextevent. protectedvirtualvoidOnClickNext(EventArgse){ EventHandlerclickNextHandler= (EventHandler)Events[EventClickNext]; if(clickNextHandler!=null){ clickNextHandler(this,e); } } //InvokesdelegatesregisteredwiththeClickPreviousevent. protectedvirtualvoidOnClickPrevious(EventArgse){ EventHandlerclickPreviousHandler= (EventHandler)Events[EventClickPrevious]; if(clickPreviousHandler!=null){ clickPreviousHandler(this,e); } } //MethodofIPostBackEventHandlerthatraisespostbackevents. voidIPostBackEventHandler.RaisePostBackEvent(stringeventArgument){ if(eventArgument=="Previous") OnClickPrevious(EventArgs.Empty); elseif(eventArgument=="Next") OnClickNext(EventArgs.Empty); } protectedoverridevoidRender(HtmlTextWriterwriter){ //Makesurethiscontrolisinaformtagwith //runat=server. if(Page!=null){ Page.VerifyRenderingInServerForm(this); } base.Render(writer); } protectedoverridevoidRenderContents(HtmlTextWriterwriter){  writer.AddAttribute(HtmlTextWriterAttribute.Onclick, Page.GetPostBackEventReference(this,"Previous"));  writer.AddAttribute("language","javascript"); writer.RenderBeginTag(HtmlTextWriterTag.Button); writer.Write(this.PreviousText); writer.RenderEndTag();  writer.AddAttribute(HtmlTextWriterAttribute.Onclick, Page.GetPostBackEventReference(this,"Next"));  writer.AddAttribute("language","javascript"); writer.RenderBeginTag(HtmlTextWriterTag.Button); writer.Write(this.NextText); writer.RenderEndTag(); } } } 

Listing 9-8 shows a page that uses the NavButtons control, and Figure 9-6 shows the page viewed in a browser.

Listing 9-8 NavButtonsTest.aspx
 <%@PageLanguage="C#"%> <%@RegisterTagPrefix="msp"Namespace="MSPress.ServerControls" Assembly="MSPress.ServerControls"%> <html> <head> <scriptrunat="server"> voidnavButtons1_ClickPrevious(objectsender,EventArgse){ label1.Text="YouclickedthePreviousbutton."; } voidnavButtons1_ClickNext(objectsender,EventArgse){ label1.Text="YouclickedtheNextbutton."; } </script> </head> <body> <formrunat="server"> <br> Clickabutton: <br> <msp:NavButtonsNextText="Next"PreviousText="Previous" runat="server"OnClickPrevious="navButtons1_ClickPrevious" OnClickNext="navButtons1_ClickNext"id="navButtons1"/> <br> <asp:LabelFont-Size="10pt"Font-Bold="true"id="label1" runat="server"/> </form> </body> </html> 
Figure 9-6. NavButtonsTest.aspx viewed in a browser. The event that is raised on the server depends on the button that is clicked.

graphics/f09hn06.jpg



Developing Microsoft ASP. NET Server Controls and Components
Developing Microsoft ASP.NET Server Controls and Components (Pro-Developer)
ISBN: 0735615829
EAN: 2147483647
Year: 2005
Pages: 183

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net