Exposing a Property: The PrimeGenerator Control ExampleNow that we have seen the main steps for authoring and deploying a server control, we'll write a control that exposes a property and does some useful work. Our next sample, PrimeGenerator , is a simple server control that computes and displays prime numbers less than or equal to a given number. The main task of our control is to render the computed primes to the client. A user of our control should be able to specify an upper limit for the primes' computation. For this purpose, we will expose a property named Number from our control. Properties are accessed similarly to the way fields are, but they are implemented as accessor methods , effectively acting as "smart" fields. (We described the property construct in Chapter 3, "Component Programming Overview.") Listing 5-3 provides the complete code for the PrimeGenerator control. PrimeGenerator derives from Control , exposes the Number property, and overrides the Render method to output the result of the computation of primes. Listing 5-3 PrimeGenerator.csusingSystem; usingSystem.Web.UI; namespaceMSPress.ServerControls{ publicclassPrimeGenerator:Control{ privateint_number; publicintNumber{ get{return_number;} set{_number=value;} } protectedoverridevoidRender(HtmlTextWriterwriter){ //Sieveisaclassthatcomputesprimes. //Wewilldefinethisclasslater. int[]primes=Sieve.GetPrimes(Number); //Noticethatwewritesuccessivestringstothe //outputstreaminsteadofconcatenatingtheminto //longerstringsbeforewriting.Thisismoreefficient //thanstringconcatenation. writer.Write("Primeslessthanorequalto:"); writer.Write(Number); writer.Write("<br>"); for(inti=0;i<primes.Length;i++){ writer.Write(primes[i]); writer.Write(""); } writer.Write("<br>"); } } } All that remains to do is implement a utility class that contains the logic for computing primes. The implementation of this class is not important for control authoring; we have included it here for completeness.
We expose the prime computation functionality from an independent class named Sieve because that functionality does not belong in a control. Listing 5-4 shows the code for the Sieve class. Listing 5-4 Sieve.csusingSystem; usingSystem.Collections; namespaceMSPress.ServerControls{ //SieveisautilityclassthatusesthesieveofEratosthenes //algorithmtocomputeprimeslessthanorequalto //agivenpositiveinteger. internalsealedclassSieve{ privateSieve(){} publicstaticint[]GetPrimes(intn){ //Useanarrayofn+1bitstocorrespondto //thenumbersfrom0ton.Initially,setallthebits //totrue.Thegoalofthecomputationistocyclethrough //thebitarrayusingthesieveofEratosthenesalgorithm //andtosetthebitscorrespondingtononprimestofalse. //Theremainingtruebitsrepresentprimes. BitArrayflags=newBitArray(n+1,true); for(inti=2;i<=(int)Math.Sqrt(n);i++){ if(flags[i]){ for(intj=i;j*i<=n;j++){ flags[i*j]=false; } } } //Countthenumberofprimes<=n. intcount=0; for(inti=2;i<=n;i++){ if(flags[i])count++; } //Createanintarraytostoretheprimes. int[]primes=newint[count]; //Checkbitflagsandpopulateprimes //arraywithnumberscorrespondingto //truebits. for(inti=2,j=0;j<count;i++){ if(flags[i])primes[j++]=i; } returnprimes; } } } Deriving from WebControlIf we derive our custom control from WebControl instead of from Control , our control inherits many additional properties, such as Font , Height , Width , and other style- related properties that enable a page developer to customize the visual appearance of the control. When deriving from WebControl , keep the following stipulations in mind:
Listing 5-5 highlights the changes to our control when it derives from WebControl . Listing 5-5 StyledPrimeGenerator.csusingSystem; usingSystem.Web.UI; usingSystem.Web.UI.WebControls; namespaceMSPress.ServerControls{ publicclassStyledPrimeGenerator:WebControl { privateint_number; publicintNumber{ get{return_number;} set{_number=value;} } protectedoverridevoidRenderContents(HtmlTextWriterwriter) { //NotethattheimplementationoftheRenderContents //methodisidenticaltotheimplementationofRenderin //PrimeGenerator. int[]primes=Sieve.GetPrimes(Number); writer.Write("Primeslessthanorequalto:"); writer.Write(Number); writer.Write("<br>"); for(inti=0;i<primes.Length;i++){ writer.Write(primes[i]); writer.Write(""); } writer.Write("<br>"); } } } Test Page for the PrimeGenerator ControlThe page shown in Listing 5-6 tests the PrimeGenerator and StyledPrimeGenerator controls. Note that StyledPrimeGenerator inherits properties such as Height , Width , ForeColor , and BackColor for free because it derives from WebControl . Listing 5-6 PrimeGeneratorTest.aspx<%@PageLanguage="C#"%> <%@RegisterTagPrefix="msp"NameSpace="MSPress.ServerControls" Assembly="MSPress.ServerControls"%> <html> <head> <scriptrunat="server"> voidButtonClicked(objectsender,EventArgse){ primegen1.Number=Int32.Parse(num1.Text); primegen2.Number=Int32.Parse(num2.Text); sprimegen1.Number=Int32.Parse(num3.Text); } </script> </head> <body> <formrunat="server"> <br> <br> <msp:PrimeGeneratorNumber="15"id="primegen1"runat="server"/> <br> <msp:PrimeGeneratorNumber="100"id="primegen2"runat="server"/> <br> <msp:StyledPrimeGeneratorNumber="51"id="sprimegen1" Width="500"Font-Name="Verdana"Font-Size="14pt" BackColor="#EEEEEE"ForeColor="Black"runat="server"/> <br> Enter3positiveintegers: <asp:TextBoxid="num1"width="50"text="0"runat="server"/> <asp:TextBoxid="num2"width="50"text="0"runat="server"/> <asp:TextBoxid="num3"width="50"text="0"runat="server"/> <br> <asp:Buttontext="Submit"id="submit" onclick="ButtonClicked"runat="server"/> <br> </form> </body> </html> When you access PrimeGeneratorTest.aspx, the output in your browser should be similar to that shown in Figure 5-3. The third output block is rendered by StyledPrimeGenerator , which is visually distinct because of values assigned to some of its style properties. Figure 5-3. The PrimeGeneratorTest.aspx page that tests the PrimeGenerator and StyledPrimeGenerator controls, viewed in a browser
|