Page view counter

The difference between understanding a concept…

Follow up posted at bottom of article

 

 

… and implementing it, can be the difference between your book being on time, and being, er, ah, well… late.

I’ve written chapters on custom controls at least a dozen times, and I’ve explained how to write custom controls at least a hundred times. You’d think I could do it in my sleep. In this first of a series of blog entries about Silverlight custom controls I’ll try to convey why creating custom controls is not difficult, but explaining it, or at least explaining it well, is.

There were custom controls in ASP.NET, in Windows Forms, in many other GUI platforms, and they’ve always been just  about the same idea. You typically had three options:

DropDownButton

Option One

The first way to create a custom control is to aggregate two or more existing controls into a new type; to make something new (or something monstrous). My favorite example is to combine a button with a DropDown to make a button whose action can change.

 

 

 

 

 

 

 

 

 

 

 

 

 

Option Two

The second approach is to derive from an existing control but to add a little new CountedButtonfunctionality. My standard  example is Clickable button, a button that knows how many times it has been clicked.

The code shown below is taken from Programming ASP.NET  but the concepts are the same across many GUI frameworks.

 

 

   1: using System;
   2: using System.ComponentModel;
   3: using System.Web.UI;
   4:  
   5: namespace CustomControls
   6: {
   7:     [DefaultProperty("Text")]
   8:     [ToolboxData("<{0}:CountedButton2 runat=server></{0}:CountedButton2>")]
   9:     public class CountedButton : System.Web.UI.WebControls.Button
  10:     {
  11:       private string displayString;
  12:  
  13:       public CountedButton(  )
  14:       {
  15:          displayString = "clicks";
  16:          InitValues(  );
  17:       }
  18:  
  19:       private void InitValues(  )
  20:       {
  21:          if (ViewState["Count"] == null)
  22:             ViewState["Count"] = 0;
  23:          this.Text = "Click me";
  24:       }
  25:    
  26:       public int Count 
  27:       {
  28:          get { return (int) ViewState["Count"]; }
  29:          set { ViewState["Count"] = value; }
  30:       }
  31:  
  32:       protected override void OnClick(EventArgs e)
  33:       {
  34:          ViewState["Count"] =  ((int)ViewState["Count"]) + 1;
  35:          this.Text = ViewState["Count"] + " " + displayString;
  36:          base.OnClick(e);
  37:       }
  38:     }
  39: }
  40:  

 

 

Option Three

And the third, typically most labor-intensive approach is to derive from a root Control object and (typically) draw the entire control and write all its logic yourself. An example that I’ve used a number of times is a custom clock face where the date travels around the circumference in Ferris Wheel like fashion and where you must draw the numbers, and the hour and minute hands and the position for the seconds indicator essentially “by hand”

CustomClock

This kind of control requires extensive coding in some environments, as shown in this cut down code listing (full and annotated listing in Programming WinForms.)

   1: public class ClockFaceCtrl : System.Windows.Forms.Control
   2: {
   3:     public ClockFaceCtrl()
   4:     {    }
   5:  
   6:     public void OnTimer(Object source, ElapsedEventArgs e)
   7:     {
   8:         Graphics g = this.CreateGraphics();
   9:         SetScale(g);
  10:         DrawFace(g);
  11:         DrawTime(g,false);
  12:         DrawDate(g);
  13:         g.Dispose();
  14:     }
  15:  
  16:     protected override void OnPaint ( PaintEventArgs e )
  17:     {     }
  18:  
  19:     private void SetScale(Graphics g)
  20:     {
  21:         g.TranslateTransform(Width / 2, Height / 2);
  22:         float inches = Math.Min(Width / g.DpiX, Height / g.DpiX);
  23:         g.ScaleTransform(inches * g.DpiX / 2000, inches * g.DpiY / 2000);
  24:     }
  25:  
  26:     private static float GetSin(float degAngle)
  27:     { return (float) Math.Sin(Math.PI * degAngle / 180f);     }
  28:  
  29:     private static float GetCos(float degAngle)
  30:     { return (float) Math.Cos(Math.PI * degAngle / 180f);     }
  31:  
  32:     private void DrawFace(Graphics g)
  33:     {
  34:         for (int i = 1; i <= numHours; i++)
  35:         {
  36:             SizeF stringSize = g.MeasureString(i.ToString(),font);
  37:             x = GetCos(i*deg + 90) * FaceRadius;
  38:             y = GetSin(i*deg + 90) * FaceRadius;
  39:             if ( currentTime.Second  == i * 5)
  40:                 g.DrawString(i.ToString(), font, greenBrush, -x, -y,format);
  41:             else
  42:                 g.DrawString(i.ToString(), font, brush, -x, -y,format);
  43:         }
  44:     }
  45:  
  46:     private void DrawTime(Graphics g, bool forceDraw)
  47:     {
  48:         rotation = GetSecondRotation();
  49:         state = g.Save();
  50:         g.RotateTransform(rotation);
  51:         g.FillEllipse(blankBrush,-25,-secondLength,50,50);
  52:         g.Restore(state);
  53:     }
  54:  
  55:     private float GetHourRotation()
  56:     { }
  57:     private float GetMinuteRotation()
  58:     { return( 360f * currentTime.Minute / 60f );  }
  59:  
  60:     private float GetSecondRotation()
  61:     { return(360f * currentTime.Second / 60f);  }
  62:  
  63:     private class LtrDraw
  64:     {    }
  65:  
  66:     private class StringDraw
  67:     { 
  68:         public StringDraw(string s, ClockFaceCtrl theControl)
  69:         {           }
  70:  
  71:         public void DrawString(Graphics g, Brush brush)
  72:         {
  73:             foreach (LtrDraw theLtr in theString)
  74:             {
  75:                 theLtr.DrawString(g,brush,theControl);
  76:             }
  77:             ClockFaceCtrl.offset += 1;
  78:         }
  79:     }
  80:  
  81:     private void DrawDate(Graphics g)
  82:     {
  83:         Brush brush = new SolidBrush(ForeColor);
  84:         sdToday.DrawString(g,brush);
  85:     }
  86: }

 

 

 

 

 

 

 

 

 

Why Is This GUI Framework Different From All Other Gui Frameworks?

Writing a templatable custom control in Silverlight is exactly the same, only totally different. That is, the architectural build/ buy/ make-do decisions are the same, and the derivation decisions are the same, but the new wrinkle is the separation of logic from visuals though a contract enforced by the Parts and States model and leveraged by the Visual State Machine.

It is to that, I will turn when I wake up, but I suddenly realized that it is 2:20 am, and I should be sleeping. Very much.

 

Follow-up
More here:  Digging Into Custom Controls

Published 12 September 2008 02:26 AM by jesseliberty
Filed under:

Comments

# The difference between understanding a concept??? said on 12 September, 2008 04:40 AM

Pingback from  The difference between understanding a concept???

# Dew Drop - September 12, 2008 | Alvin Ashcraft's Morning Dew said on 12 September, 2008 09:45 AM

Pingback from  Dew Drop - September 12, 2008 | Alvin Ashcraft's Morning Dew

# Community Blogs said on 12 September, 2008 04:16 PM

Nikolay Raychev on SL and Localization, Chris Koenig on Style, WPF and SL, ux.artu.tv with developer

# Jesse Liberty - Silverlight Geek said on 12 September, 2008 09:17 PM

Last night’s post was something of a preface, but let’s get started. [ For those of you who crave the

# Microsoft Weblogs said on 12 September, 2008 10:26 PM

Last night’s post was something of a preface, but let’s get started. [ For those of you who crave the

# Mirrored Blogs said on 12 September, 2008 10:28 PM

Last night’s post was something of a preface, but let’s get started. [ For those of you who crave the

# 2008 September 13 - Links for today « My (almost) Daily Links said on 13 September, 2008 03:43 AM

Pingback from  2008 September 13 - Links for today &laquo; My (almost) Daily Links

# Jesse Liberty - Silverlight Geek said on 21 September, 2008 08:55 AM

It will be helpful as we explore custom controls to have a common starting project. You may&#160; remember

# Mirrored Blogs said on 21 September, 2008 09:11 AM

It will be helpful as we explore custom controls to have a common starting project. You may&#160; remember

# Microsoft Weblogs said on 21 September, 2008 09:17 AM

It will be helpful as we explore custom controls to have a common starting project. You may&#160; remember

# Leonai_art said on 22 September, 2008 01:31 PM

Just wanted to comment mentioning the level of amusement gained from the line, "Writing a templatable custom control in Silverlight is exactly the same, only totally different."  

Thank you for the chuckle.

# Jesse Liberty - Silverlight Geek said on 09 October, 2008 09:48 AM

Over the past month I've posted half a dozen min-articles about creating custom controls that can interact

# Microsoft Weblogs said on 09 October, 2008 10:10 AM

Over the past month I've posted half a dozen min-articles about creating custom controls that can interact

# Mirrored Blogs said on 09 October, 2008 10:37 AM

Over the past month I&#39;ve posted half a dozen min-articles about creating custom controls that can

# Custom Controls - the handling at Blog von J??rgen Ebner said on 10 October, 2008 06:15 AM

Pingback from  Custom Controls - the handling at Blog von J??rgen Ebner

# Jesse Liberty - Silverlight Geek said on 05 December, 2008 03:01 PM

&#160; &#160; I have completed the four part video series Creating Skinnable Customer Controls and I

# Microsoft Weblogs said on 05 December, 2008 03:52 PM

&#160; &#160; I have completed the four part video series Creating Skinnable Customer Controls and I

# Erstellen von anpassbaren Custom Control at Programming with Silverlight, WPF & .NET said on 08 December, 2008 04:07 PM

Pingback from  Erstellen von anpassbaren Custom Control at Programming with Silverlight, WPF &amp; .NET

# Jesse Liberty - Silverlight Geek said on 22 December, 2008 05:34 PM

When we started creating How Do I videos, the idea was to have stand alone videos that do not depend

# Microsoft Weblogs said on 22 December, 2008 06:17 PM

When we started creating How Do I videos, the idea was to have stand alone videos that do not depend

# Templates & Custum Controls at Programming with Silverlight, WPF & .NET said on 23 December, 2008 08:29 AM

Pingback from  Templates &#038; Custum Controls at Programming with Silverlight, WPF &amp; .NET

# Templates & Custum Controls at Programming with Silverlight, WPF & .NET said on 23 December, 2008 08:32 AM

Pingback from  Templates &#038; Custum Controls at Programming with Silverlight, WPF &amp; .NET

# Jesse Liberty - Silverlight Geek said on 29 May, 2009 04:57 PM

&#160; &#160; I had the pleasure of presenting What’s New In Silverlight 3 both at TechEd this year and

# Microsoft Weblogs said on 29 May, 2009 05:42 PM

I had the pleasure of presenting What’s New In Silverlight 3 both at TechEd this year and then again

# Programming with Silverlight, WPF & .NET » Was ist neu in Silverlight 3 said on 05 June, 2009 06:25 AM

Pingback from  Programming with Silverlight, WPF &amp; .NET &raquo; Was ist neu in Silverlight 3

# Top-silverlight » Blog Archive » What???s New In Silverlight 3 said on 06 June, 2009 07:46 AM

Pingback from  Top-silverlight  &raquo; Blog Archive   &raquo; What???s New In Silverlight 3