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;
   7:  namespace HC.Web.Controls
   8:  {
  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;
  20:           private string _DefaultWatermarkText = "Watermark";
  21:          #endregion
  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:           }
  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:           }
  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:           }
  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:           }
 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:          }
 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
 142:          protected override void RecreateChildControls()
 143:          {
 144:              EnsureChildControls();
 145:          }
 147:          protected override void CreateChildControls()
 148:          {
 149:              SetTextBoxIdIfEmpty();
 150:              this.Controls.Add(textBox);
 151:              watermarkExtender.ID = textBox.ID + "_waterMarkExtender";
 152:              watermarkExtender.TargetControlID = textBox.ID;
 154:              if (WatermarkText == "")
 155:              {
 156:                  WatermarkText = DefaultWatermarkText;
 157:              }
 158:              this.Controls.Add(watermarkExtender);
 159:          }
 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
 175:           #region C'tor
 176:           public WatermarkTextBox()
 177:           {
 178:               textBox = new TextBox();
 179:               watermarkExtender = new TextBoxWatermarkExtender();
 180:           }
 181:           #endregion
 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.

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…

I am really proud that my first .NET Magazine article is publiced.
I wrote this article with my co-worker Dennis van de Laar. The topic is AJAX and Javascript.

Dutch .NET Magazine #22

 Ajax is niet meer weg te denken

It is a small download, it''s PDF and it is Dutch 

Henry Cordes
My thougts exactly...

My fellow-avanade dude Dennis pointed me out the following site:
Lost in Tangent

On this site there are lots links to of tutorials, walkthroughs of the ADO.NET Data Services (formerly "Astoria"). Astoria was a project from Microsoft's 'Data team'. A team that works on all data related stuff in and for the .NET Framework, like the Entity Framework. The ADO.NET Data Services is the name that is now used for project 'Astoria', after a few CTP's now the ASP.NET 3.5 Extensions preview release contains the first production release. With these Extensions Microsofts paves the way for more 'in-between' releases. We do not always have to wait for a major .NEt Framework release that contains new functionality. The ASP.NET AJAX Framework had the premiere with this in-between release methodology. It was a success and with the .NET Framework 3.5 just released, ADO.NET Data services is here with some more goodies.
These services are a combination of patterns and libraries that enables any data store to be exposed as a data service, naturally integrating with the Web. Also these services can be consumed by Web clients. It is built making heavy use of the Entity Framework. 

I quote: "ADO.NET Data Services uses URIs to point to pieces of data and simple, well-known formats to repirst production release.resent that data, such as JSON and ATOM/APP. This results in data being exposed to Web clients as a REST-style resource collection, addressable with URIs that agents can interact with using standard HTTP verbs such as GET, POST, or DELETE."

I played with it and it was remarkebly easy to get data on the client using Javascript and because JSON is a supported format, it is easy to get these objects directly from the server tier. I think this could be a really helpfull if you want to create Client-centric AJAX Webapps. The use of formats like RSS, JSON and Atom is brilliant in simplicity. The ADO.NET Data Services are released in the ASP.NET 3.5 Extensions preview release.

If you are interested in what it is all about, take a look here

Henry Cordes
My thoughts exactly

Microsoft Press have just released an e-book on Visual Studio 2008 technologies and are giving it away for free. The e-book includes excerpts from three recent book releases and provides a wealth of information and insights from top experts:

Look here

Henry Cordes
My thoughts exactly...

This edition of the DevDays was totally in the light of XAML, WPF (Windows Presentation Foundation), WCP (Windows Communication Foundation) and last but not least: Silverlight. The last few editions where always about new technology, this year Microsoft tried to listen to the community.  With the result that they also put in some sessions on todays technology and how to make good use of it. Think AJAX, Asynchronous ASP.Net Pages and Web Services.

In the Keynote we saw Scott Guthrie who showed us Silverlight and Microsoft Expression.
We saw an application called: 'Top Banana', which is a video editing application in the browser. It is impressive technology, I know we already have Flash, but Silverlight integrates the .NET framework and supports ASP.NET AJAX. I don't know if you ever worked with Flash and .NET (through remoting and actionscript), than I think you can appreciate this integration.

I saw a lot of WPF and WCF. I see the advantages a lot can be daone declarative through XAML.
In WPF the UI (User Interface) can be made in XAML and a lot can be nested (a button can contain a movie, or a listbox etc.). Your own objects can be accessed in XAML if you addd your own namespace in the root element of the XAML Document:
If you want to try you can use 'Visual Studio ORCAS', which in the future will be 'Visual studio 2008', but if you want to use a more 'drag and drop' approach building a UI, use 'Blend'. If you really want to know more go here: http://wpf.netfx3.com/. Animations are supported in XAML, this means declaritive animations! Databinding support, WPF supports databinding.

I heard about XAML Browser Applications(XBAPs), are WPF applications you can run in the browser, these apps are deployed using the 'Click once' deployment technique.
The advantages are:

  • Are not installed  
     – No Start Menu or Add/Remove Programs presence  
     – Use ClickOnce for deployment  
  • Run in the browser  
     – Familiarity of web browsing  
  • Are “online only” apps  
     – Require access to the  
     deployment location  
     – Always latest version  
  • Run in a security sandbox  
     – Have no security or installation prompt  

These Devdays, I became a great fan of Mark miller, he works with Devexpress and I think Coderush is an app he worked on.
He is a great performer with something to tell, this guy keeps your interest the whole session. The first day I attended his 'Rockin' & Rollin' with WCF and WPF' session, he built an Airhockey client-server App with WPF and WCF. He showed a lot about how this app is built and he also entertained the audience real well. The second day the last session I attended was Mark Miller's 'The Science of a Great UI' session. He really had a big audience, a lot of people wanted to see this session. Unless the blue screen of death it was a interesting and entertaining session.
I had a great time.

Henry Cordes
My thoughts exactly...