1. Introduction
The star controls developed in previous tasks are only applicable to static display. For example, they indicate the popularity of a software. However, many websites also want users to rate a certain information, finally, the popularity of the information is calculated to make the data more objective and credible. Therefore, the original Star-level control needs to be improved to enable the user to dynamically score the information, as shown in the following figure:
The first row in the figure shows the status of the score control. The developer processes the score event and outputs the selected score on the page; the second row in the figure shows another scoring status-move the mouse to the star image, and then use the Red Star to prompt the user.
2. Analysis
For this control, we need to add two features based on the original control:
1. move the cursor over the indicator to display the score selected by the user.
2. When you click the mouse, the system can send back to the server and expose the corresponding event to be handled by the developer.
For the first requirement, you can handle the mouse event in Javascript. When the onmouseover event is triggered, you can determine which star pattern the current mouse is hovering over, and then display the red star pattern. There are also some tips for displaying a pattern. You can embed layers in the layer (DIV) of the original Star Pattern and set the background of the layer to a red star pattern, during page loading, this layer should not be displayed (set the width to 0), and set the width of this layer when hovering over the mouse, we only need to note that this layer can overwrite the background layer.
You also need to consider that you need to hide the layer when moving the mouse out. You only need to handle the onmouseout event and set the layer width to 0 again to achieve the purpose of hiding the layer.
For the second requirement, first expose a public event in the custom control to enable developers to subscribe to the event, and then generate a send-back script on the client, this script can be executed and submitted to the server when you click (The onclick event in Javascript is triggered.
To generate a send-back script and enable the custom control to implement the ipostbackeventhandler interface, this interface defines the methods that ASP. NET Server controls must implement to handle send-back events.
After submitting the event to the server, the custom control calls the public event and replaces the star pattern with a yellow background to mark the user's score. We can also add another layer to the background layer, use the same as the first requirementAlgorithmYou can overwrite the background layer.
You must be sure that you are not allowed to score again after the user scores (hide the layer of the user's current mouse hover and select the score ).
The final problem to be considered is that the custom control uses the server-side control as the container to display images. To avoid the problem of placing multiple custom controls on the page, you must ensure that the client numbers generated by each server control are unique at this time. You must have come up with a solution to achieve the inamingcontainer interface.
3. Implementation
3.1 create a poststart class inherited from webcontrol in the controllibrary class library of the controlsolution solution, and enable it to implement ipostbackeventhandler and inamingcontainer interfaces:
Using system; using system. componentmodel; using system. web. ui; using system. web. UI. webcontrols; using system. web. UI. htmlcontrols; namespace controllibrary {public class poststar: webcontrol, ipostbackeventhandler, inamingcontainer {}}
3.2 add score and comment attributes for the custom control:
[Defaultvalue (0)] public int score {get {object OBJ = viewstate ["score"]; return OBJ = NULL? 0: convert. toint32 (OBJ);} internal set {viewstate ["score"] = value ;}} Public String comment {get {object OBJ = viewstate ["comment"]; return OBJ = NULL? String. Empty: Convert. tostring (OBJ);} set {viewstate ["comment"] = value ;}}
3.3 override the createchildcontrols method to create a child control hierarchy. In this method, call the createcontrolhierarchy method:
Protected override void createchildcontrols () {base. createchildcontrols (); createcontrolhierarchy ();}
3.4 compile the createcontrolhierarchy method. In this method, create a table with one row and two columns in the Child control set. Then call the createcomment method to output comments on the first page, then, the createstart method is called to create a star image:
Protected virtual void createcontrolhierarchy () {Table = new table (); tablerow ROW = new tablerow (); table. rows. add (ROW); tablecell comment = new tablecell (); createcomment (comment); row. cells. add (comment); tablecell stars = new tablecell (); createstars (stars); row. cells. add (stars); this. controls. add (table );}
3.5 implement the createcomment method and assign the comment text to the text attribute of the Cell:
Private void createcomment (tablecell cell) {Cell. Text = comment ;}
3.6 compile the createstars method for creating a star image. In this method, the registercss method is called to register the CSS style table file used to the page (this file is published as a resource file ), next, the createbackpanel, createcurrentpanel, and createchangepanel methods are called to create the background layer, identify the selected layer, and the layer that represents the current mouse hover. The createlist method is also called to create a list, finally, organize the layers and lists according to the hierarchy (using the panel control presentation layer ):
Private void createstars (tablecell cell) {registercss (); string starpath = page. clientscript. getwebresourceurl (this. getType (), "controllibrary.image.stars.gif"); Panel panbg = createbackpanel (starpath); cell. controls. add (panbg); Panel pancur = createcurrentpanel (starpath); Panel panchange = createchangepanel (starpath); htmlgenericcontrol ul = createlist (); panbg. controls. add (UL); panbg. controls. add (pancur); pancur. controls. add (panchange );}
3.7 implement the registercss method, obtain the style sheet resource file, and use the htmllink class to register the style sheet:
Private void registercss () {string CSS = page. clientscript. getwebresourceurl (this. getType (), "controllibrary.css.star.css"); htmllink link = new htmllink (); Link. href = CSS; Link. attributes. add ("rel", "stylesheet"); Link. attributes. add ("type", "text/CSS"); page. header. controls. add (Link );}
3.8 compile the createbackpanel, createcurrentpanel, createchangepanel, and createlist Methods:
Private panel createbackpanel (string starpath) {panel panbg = new Panel (); panbg. id = "divbg"; panbg. style. add (htmltextwriterstyle. backgroundimage, starpath); panbg. cssclass = "Stars"; return panbg;} private panel createcurrentpanel (string starpath) {panel pancur = new Panel (); pancur. id = "divcur"; pancur. style. add (htmltextwriterstyle. backgroundimage, starpath); pancur. cssclass = "current"; return pancur;} private panel createchangepanel (string starpath) {panel panchange = new Panel (); panchange. id = "divchange"; panchange. style. add (htmltextwriterstyle. backgroundimage, starpath); panchange. cssclass = "change"; return panchange;} private htmlgenericcontrol createlist () {htmlgenericcontrol ul = new htmlgenericcontrol ("Ul"); ul. id = "ulist"; ul. attributes. add ("class", "ulist"); For (INT I = 0; I <5; I ++) {htmlgenericcontrol li = new htmlgenericcontrol ("Li"); Li. attributes. add ("value", (I + 1 ). tostring (); ul. controls. add (LI);} return ul ;}
3.10 rewrite the render method to render the control. This method calls the preparecontrolforreader method:
Protected override void render (htmltextwriter writer) {preparecontrolforrender (); base. Render (writer );}
3.11 implement preparecontrolforrender. In this method, list items in the list are retrieved according to the control level and JavaScript events are registered:
Private void preparecontrolforrender () {If (this. controls. count <1) return; Table = (table) This. controls [0]; table. cellspacing = 0; table. cellpadding = 0; tablecell cell = table. rows [0]. cells [1]; Panel pancur = (panel) cell. controls [0]. controls [1]; Panel panchange = (panel) pancur. controls [0]; htmlgenericcontrol ul = (htmlgenericcontrol) cell. controls [0]. controls [0]; for (INT I = 0; I <ul. controls. count; I ++) {htmlgenericcontrol li = (htmlgenericcontrol) ul. controls [I]; Li. attributes. add ("onmouseover", "document. getelementbyid ('"+ panchange. clientid + "'). style. width = '"+ 16 * (I + 1) +" PX'; "); Li. attributes. add ("onmouseout", "document. getelementbyid ('"+ panchange. clientid + "'). style. width = '0px '; "); Li. attributes. add ("onclick", page. clientscript. getpostbackclienthyperlink (this, (I + 1 ). tostring ()));}}
You can see that the server sending back is triggered in the Click Event (onclick) of the list item, which is based on page. clientscript. the getpostbackclienthyperlink method is used to pass two parameters. The first parameter references the server control that causes the sending back, and the second parameter identifies the parameters passed during sending back, the index of the star pattern is passed here.
|
Why not register the Javascript script while creating the list? This is because when the createchildcontrols method is executed, the clientid of the control on each server has not yet been generated. At this time, the registered script will cause an error during client operations. |
3.12 to trigger an event, first write the event parameter class stareventargs, which defines the score attribute to save the score:
Public class stareventargs: eventargs {public int score {Get; Set ;}}
3.13 declare the event attribute in poststar. Note that this is different from the previous task. Declare the event as a private field and expose it through the attribute. (This usage is more recommended than the previous one ):
Private event eventhandler <stareventargs> _ postscore; public event eventhandler <stareventargs> postscore {Add {_ postscore + = value;} remove {_ postscore-= value ;}}
3.14 compile the onpostscore method call event and obtain the corresponding layer from the control level to display the fixed score:
Private void onpostscore (Object sender, stareventargs e) {If (_ postscore! = NULL) _ postscore (sender, e); tablecell cell = (table) This. controls [0]). rows [0]. cells [1]; Panel pancur = (panel) cell. controls [0]. controls [1]; pancur. style. add ("width", E. score * 16 + "PX"); Panel panchange = (panel) pancur. controls [0]; panchange. style. add ("display", "NONE"); htmlgenericcontrol ul = (htmlgenericcontrol) cell. controls [0]. controls [0]; ul. style. add ("display", "NONE ");}
3.15 implement the raisepostbackevent method of the ipostbackeventhandler interface. After the client causes the server to send back, this method is executed and the corresponding parameters are passed, in this method, we only need to make sure that all the child controls have been created, and then raise the corresponding event to set properties:
Public void raisepostbackevent (string ARGs) {If (! String. isnullorempty (ARGs) {ensurechildcontrols (); int score = convert. toint32 (ARGs); stareventargs E = new stareventargs (); E. score = score; onpostscore (this, e );}}
3.16 create a test page on the web site and register and declare the custom control:
<% @ Register tagprefix = "cc" assembly = "controllibrary" namespace =? Controllibrary? %> <CC: poststar id = "star" runat = "server" comment = "Windows XP" onpostscore = "star_postscore"/>
Appendix: style sheet file:
. Stars {width: 80px; Height: 16px; text-align: Left; overflow: hidden; position: relative; Background: url(stars.gif) 0px-32px repeat-X ;}. stars. ulist {list-style: none; position: absolute; bottom: 0px; margin: 0px; padding: 0 ;}. stars. ulist Li {display: inline; float: Left; width: 16px; Height: 16px; cursor: pointer; overflow: hidden ;}. stars. current {width: 0px; Height: 16px; Background: url(stars.gif) 0px 0px repeat-X ;}. stars. change {width: 0px; Height: 16px; Background: url(stars.gif) 0px-16px repeat-X ;}
4. Summary
In this task, we created a custom control that can be scored by users. The poststart class inherits the iposteven thandler interface to trigger server submission. By introducing this interface, we can make any control cause server submission as needed-you only need to register the corresponding JavaScript event. To prevent errors when multiple scoring controls are used on the page, we have implemented the inamingcontainer interface. In the next task, we will introduce the development method of custom data binding controls.
ASP. NET Custom ControlsArticle
Preface
Simple star control on the first day
Star controls with custom styles the next day
On the third day, use the star widget in the control status.
Fold panel custom controls on the fourth day
Star controls that can be scored on the fifth day
Star controls that can be bound to data sources on the sixth day
Develop list controls with rich features on the seventh day
Metric days: displays the data binding controls for multiple entry star rating
The ninth day custom gridview
Datalist that implements the paging function on the tenth day
Download all source code
Download this series of articles in PDF