Looking at MIX http://live.visitmix.com I found out Silverlight 3.0 BETA is out. Download Silverlight 3.0 BETA

But quickly checking out ASP.NET MVC Framework at (http://www.asp.net/mvc/).

I see ASP.NET MVC 1.0 is live!

Download ASP.NET MVC 1.0

I am going to give it a testride!

Henry Cordes
My thoughts exactly…


SDN Article on MVC Framework

Published 3/9/2009 by Henry in ASP.NET | C#
Tags: ,

My article (in dutch) with the title: ASP.NET Webapplications finally unit-testable, or (ASP.NET webapplicaties eindelijk unit-testbaar in dutch) is been published in the 100th edition of the SDN Magazine (Software Developers Network). SDN 100th Magazine in pdf format and is available for download.

VP100100th SDN Magazine

Henry Cordes
My thoughts exactly…


I am in the middle of the analysis fase for the project I mentioned in the post about using WCSF for ASP.NET (and Sharepoint) Usercontrols.  I know how I am going to integrate the UserControls into SharePoint in such a way, that the controls can be used in SharePoint and in custom ASP.NET Web applications.
I am going to use the MVP pattern without the help of WCSF or CWAB, but with the help of Unity. I will post an article in more detail about this in the near future.
For now I want to share a simple ASP.NET composite control I need, to make it easier to have watermark functionality for every textbox on a page, without having to add a TextBoxWatermarkExtender for every TextBox.

The way I accomplish this is by creating a composite control with a TextBox and a TextboxWatermarkExtender on it.

The code:

   1:  using System;
   2:  using System.ComponentModel;
   3:  using System.Web.UI;
   4:  using System.Web.UI.WebControls;
   5:  using AjaxControlToolkit;
   6:   
   7:  namespace HC.Web.Controls
   8:  {
   9:   
  10:       [DefaultProperty("Text"),
  11:        ValidationProperty("Text"),
  12:        Description("TextBox with Watermark capabilities"),
  13:        ToolboxData("<{0}:WatermarkTextBox runat=server></{0}:WatermarkTextBox>")]
  14:      public class WatermarkTextBox: CompositeControl
  15:      {
  16:          #region Private members
  17:           private TextBox textBox;
  18:           private TextBoxWatermarkExtender watermarkExtender;
  19:   
  20:           private string _DefaultWatermarkText = "Watermark";
  21:          #endregion
  22:   
  23:          #region Properties
  24:           /// <summary>
  25:           /// Gets the ClientID of the textbox
  26:           /// </summary>
  27:          [Bindable(true),
  28:          Category("Behavior"),
  29:          Description("The TextBoxClientID of the WatermarkTextBox"),
  30:          DefaultValue("")]
  31:          public string TextBoxClientID
  32:           {
  33:               get
  34:               {
  35:                   EnsureChildControls();
  36:                   return textBox.ClientID;
  37:               }
  38:           }
  39:   
  40:           /// <summary>
  41:           /// Gets or sets the Text in the textbox
  42:           /// </summary>
  43:           [Bindable(true),
  44:          Category("Behavior"),
  45:          Description("The text of the textbox"),
  46:          DefaultValue("")]
  47:           public string Text
  48:           {
  49:               get
  50:               {
  51:                   EnsureChildControls();
  52:                   return textBox.Text;
  53:               }
  54:               set
  55:               {
  56:                   EnsureChildControls();
  57:                   textBox.Text = value;
  58:               }
  59:           }
  60:   
  61:           /// <summary>
  62:           /// Gets or sets the CssClass of the Textbox
  63:           /// </summary>
  64:           [Bindable(true),
  65:           Description("The css class that is used when the textbox is in it's normal state"),
  66:           Category("Appearance"),
  67:           DefaultValue("")]
  68:           public override string CssClass
  69:           {
  70:               get
  71:               {
  72:                   EnsureChildControls();
  73:                   return textBox.CssClass;
  74:               }
  75:               set
  76:               {
  77:                   EnsureChildControls();
  78:                   textBox.CssClass = value;
  79:               }
  80:           }
  81:   
  82:           /// <summary>
  83:           /// Gets or sets the CssClass for the watermark state of the Textbox
  84:           /// </summary>
  85:           [Bindable(true),
  86:            Description("The css class that is used when the textbox is in it's watermark state"),
  87:            Category("Appearance"),
  88:            DefaultValue("")]
  89:           public string WatermarkCssClass
  90:           {
  91:               get 
  92:               { 
  93:                   EnsureChildControls();
  94:                   return watermarkExtender.WatermarkCssClass;
  95:               }
  96:               set 
  97:               { 
  98:                   EnsureChildControls();
  99:                   watermarkExtender.WatermarkCssClass = value;
 100:               }
 101:           }
 102:   
 103:           /// <summary>
 104:           /// Gets or sets the Text for the watermark
 105:           /// </summary>
 106:          [Bindable(true),
 107:           Category("Appearance"), 
 108:           Description("The (watermark)text that is shown when the textbox is in it's watermark state"),
 109:           DefaultValue("")]
 110:          public string WatermarkText 
 111:          {
 112:               get 
 113:               { 
 114:                   EnsureChildControls();
 115:                   return watermarkExtender.WatermarkText;
 116:               }
 117:               set 
 118:               { 
 119:                   EnsureChildControls();
 120:                   watermarkExtender.WatermarkText = value;
 121:               }
 122:          }
 123:   
 124:           /// <summary>
 125:           /// Gets or sets DefaultWatermarkText, cannot be empty
 126:           /// </summary>
 127:          [Bindable(true),
 128:          Category("Appearance"),
 129:          Description("The default (watermark)text that is shown when the textbox is in it's watermark state, and the WatermarkText property is empty"),
 130:          DefaultValue("")]
 131:          public string DefaultWatermarkText
 132:          {
 133:              get { return _DefaultWatermarkText; }
 134:              set 
 135:              { 
 136:                  if (value.Length > 0)
 137:                      _DefaultWatermarkText = value; 
 138:              }
 139:          }
 140:          #endregion
 141:   
 142:          protected override void RecreateChildControls()
 143:          {
 144:              EnsureChildControls();
 145:          }
 146:   
 147:          protected override void CreateChildControls()
 148:          {
 149:              SetTextBoxIdIfEmpty();
 150:              this.Controls.Add(textBox);
 151:              watermarkExtender.ID = textBox.ID + "_waterMarkExtender";
 152:              watermarkExtender.TargetControlID = textBox.ID;
 153:   
 154:              if (WatermarkText == "")
 155:              {
 156:                  WatermarkText = DefaultWatermarkText;
 157:              }
 158:              this.Controls.Add(watermarkExtender);
 159:          }
 160:   
 161:          #region Worker Methods
 162:          /// <summary>
 163:          /// Fills textBox ID if empty.
 164:          /// Format: ID + '_textBox'
 165:          /// </summary>
 166:           private void SetTextBoxIdIfEmpty()
 167:          {
 168:              if (string.IsNullOrEmpty(textBox.ID))
 169:              {
 170:                  textBox.ID = this.ID + "_textBox";
 171:              }
 172:          }
 173:          #endregion
 174:        
 175:           #region C'tor
 176:           public WatermarkTextBox()
 177:           {
 178:               textBox = new TextBox();
 179:               watermarkExtender = new TextBoxWatermarkExtender();
 180:           }
 181:           #endregion
 182:   
 183:      }
 184:  }

Listing: 1

As you can see in the code in listing 1,in the override of the CreateChildControls the actual adding of the controls to the control collection of the composite container is done.
It is important to make sure the textbox has a valid ID. Than you need to set the TargetControlID of the TextboxWatermarkExtender equal to the ID of the TextBox and the WatermarkText needs to be filled.

EnsureChildControls()
When you built a composite control make sure to call EnsureChildControls, so you can be sure the controls are accesible and no object reference not set exception is thrown.
A simple but quite useful example.

Henry Cordes
My thoughts exactly…