

Series  - Create a UserControl with Silverlight 2.0 Beta x  

Part II - Create a UserControl with SilverLight 2.0 Beta


I installed:

  • Microsoft Expression Design
  • Microsoft Expression Blend 2.5 March 2008 Preview
  • Microsoft Visual Studio 2008
  • Microsoft Silverlight Tools Beta 1 for Visual Studio 2008


Create Solution and projects

Create Silverlight Application


  2. Add a Website project to your solution
  3. Add a Web Application Project to your solution


Select hosting application type



Open in MS Blend


Add new item to Silverlight application project in Blend Add New Item

Select UserControl as template and give the control a name.

Give the xaml file for your UserControl a name New Item


Rename the UserControl in blend Rename Control


Select LayoutRoot Grid in Blend Select LayoutRoot


Background brush

In the contextmenu choose "Reset" and the background is transparent

No brush


From the toolbox select an Ellipse

Select Ellipse


Male symbol inside Microsoft Expression Design Male Symbol


Compounded path

and paste into your control in Blend.

Male symbol pasted into Blend Path inside Blend Control


Symbols have color Colors added

And the result in Xaml is this:

   1:  <UserControl
   6:      mc:Ignorable="d"

   7:      x:Class="HC.Silverlight.Tyout.GenderChooser"
  11:          <Path x:Name="MalePath"    
  12:              MouseLeftButtonDown="MalePath_MouseLeftButtonDown" 
  13:              MouseEnter="MalePath_MouseEnter"    
  14:              MouseLeave="MalePath_MouseLeave"   
  15:              Stretch="Fill" StrokeThickness="10" 
  16:              StrokeLineJoin="Round" 
  17:              Stroke="#4C0E1B4B" 
  18:              Data="M71.182777,43.484818 C88.632889,57.770176 91.340874,83.323097 77.231247,
  19:                  100.56004 C63.121323,117.79601 37.536755,120.18899 20.086346,
  20:                  105.90402 C2.6360354,91.620079 -0.071950652,66.066154 14.037977,
  21:                  48.829205 C28.147804,31.592951 53.732468,29.20006 71.182777,
  22:                  43.484818 z M71.687004,42.605003 L102.30298,5.2050009 L104.313,
  23:                  34.850189 M71.437004,42.401001 L102.053,5.000001 L72.594521,8.885973" 
  24:              Height="120.23" 
  25:              HorizontalAlignment="Left" 
  26:              Margin="2.93199992179871,2.15100002288818,0,37.6189994812012" 
  27:              VerticalAlignment="Stretch" 
  28:              Width="109.313" 
  29:              d:LayoutOverrides="Width"/>
  30:          <Path x:Name="FemalePath"  
  31:              MouseLeftButtonDown="FemalePath_MouseLeftButtonDown"    
  32:              MouseEnter="FemalePath_MouseEnter"    
  33:              MouseLeave="FemalePath_MouseLeave"   
  34:              Stretch="Fill"   

  35:              StrokeThickness="10"   
  36:              StrokeLineJoin="Round"   
  37:              Stroke="#4CF502E4"   
  39:                  126.833C 53.1151,126.833 34.8333,108.775 34.8333,86.5C 34.8333,64.2245 53.115,46.1667 75.6667,
  40:                  46.1667 Z M 76.5,126.5L 76.5,185.167M 103.833,159.167L 48.8333,159.167"   
  41:              HorizontalAlignment="Left"   
  42:              Margin="122.833000183105,0.166999995708466,0,10.8330001831055"   
  43:              Width="91.667"   
  44:              d:LayoutOverrides="Width"/>
  45:      </Grid>
  46:  </UserControl>

Listing 1




   1:  namespace HC.Silverlight.Tryout
   2:  {
   3:      #region Enums
   4:      /// <summary>
   5:      /// Tells which Gender
   6:      /// </summary>
   7:      public enum GenderChoice
   8:      {
   9:          /// <summary>
  10:          /// Gender for man
  11:          /// </summary>
  12:          Male = 0,
  13:          /// <summary>
  14:          /// Gender for woman
  15:          /// </summary>
  16:          Female = 1,
  17:          /// <summary>
  18:          /// Not sure :-)
  19:          /// </summary>
  20:          Unknown = 2
  21:      }
  23:      #endregion
  25:      #region Delegates
  26:      /// <summary>
  27:      /// Handles GenderChosen Event
  28:      /// </summary>
  32:  #endregion
  34:      public partial class GenderChooser : UserControl
  35:      {
  36:          #region Events
  37:          /// <summary>
  38:          /// GenderChosen
  39:          /// </summary>
  40:          public event GenderChosenEventHandler GenderChosen;
  41:          #endregion
  43:          #region EventHandler
  44:          /// <summary>
  45:          /// Raises event, if EventHandler not null
  46:          /// </summary>
  48:          private void OnGenderChosen(object sender, GenderChoice selectedGender)
  49:          {
  50:              if (GenderChosen != null)
  51:              {
  52:                  GenderChosen(sender, selectedGender);
  53:              }
  54:          }
  55:          #endregion
  58:          #region Privates
  59:          private GenderChoice _Gender = GenderChoice.Unknown;
  64:          #endregion
  66:          #region Properties
  68:          #region Colors
  69:          /// <summary>
  71:          /// </summary>
  72:          public SolidColorBrush MaleColorDisabled

  73:          {
  74:              get { return _MaleColorDisabled; }
  75:              set { _MaleColorDisabled = value; }
  76:          }
  78:          /// <summary>
  80:          /// </summary>
  81:          public SolidColorBrush FemaleColorDisabled
  82:          {
  83:              get { return _FemaleColorDisabled; }
  84:              set { _FemaleColorDisabled = value; }
  85:          }
  87:          /// <summary>
  88:          /// Gets or sets MaleColor
  89:          /// </summary>
  90:          public SolidColorBrush MaleColor
  91:          {
  92:              get { return _MaleColor; }
  93:              set { _MaleColor = value; }
  94:          }
  96:          /// <summary>
  97:          /// Gets or sets FemaleColor
  98:          /// </summary>
  99:          public SolidColorBrush FemaleColor
 100:          {
 101:              get { return _FemaleColor; }
 102:              set { _FemaleColor = value; }
 103:          }

 104:          #endregion
 106:          /// <summary>
 107:          /// Gets or sets GenderChoice
 108:          /// </summary>
 109:          public GenderChoice Gender
 110:          {
 111:              get { return _Gender; }
 112:              set 
 113:              { 
 114:                  _Gender = value;
 115:                  SetColorAccordingToChoice();
 116:                  OnGenderChosen(this, _Gender);
 117:              }
 118:          }
 119:          #endregion
 121:          #region C'tor
 122:          public GenderChooser()
 123:          {
 124:              // Required to initialize variables
 125:              InitializeComponent();
 127:          }

 128:          #endregion
 130:          #region MouseEvents
 131:          private void MalePath_MouseEnter(object sender, MouseEventArgs e)
 132:          {
 133:              MalePath.Stroke = MaleColor;
 134:          }
 136:          private void MalePath_MouseLeave(object sender, MouseEventArgs e)
 137:          {
 138:              if (Gender == GenderChoice.Male)
 139:              {
 140:                  MalePath.Stroke = MaleColor;
 141:              }
 142:              else
 143:              {
 144:                  MalePath.Stroke = MaleColorDisabled;
 145:              }
 146:          }
 148:          private void FemalePath_MouseEnter(object sender, MouseEventArgs e)
 149:          {
 150:              FemalePath.Stroke = FemaleColor;
 151:          }
 154:          private void FemalePath_MouseLeave(object sender, MouseEventArgs e)
 155:          {
 156:              if (Gender == GenderChoice.Female)
 157:              {
 158:                  FemalePath.Stroke = FemaleColor;

 159:              }
 160:              else
 161:              {
 162:                  FemalePath.Stroke = FemaleColorDisabled;
 163:              }
 164:          }
 167:          private void MalePath_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
 168:          {
 169:              Gender = GenderChoice.Male;
 170:          }
 172:          private void FemalePath_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
 173:          {
 174:              Gender = GenderChoice.Female;
 175:          }

 177:          #endregion
 179:          #region Private Methods
 180:          /// <summary>
 182:          /// </summary>
 183:          private void SetColorAccordingToChoice()
 184:          {
 185:              switch (Gender)
 186:              {
 187:                  case  GenderChoice.Unknown:
 188:                      MalePath.Stroke = MaleColorDisabled;
 189:                      FemalePath.Stroke = FemaleColorDisabled;
 190:                      break;
 191:                  case GenderChoice.Female:
 192:                      MalePath.Stroke = MaleColorDisabled;
 193:                      FemalePath.Stroke = FemaleColor;
 194:                      break;
 195:                  case GenderChoice.Male:
 196:                      MalePath.Stroke = MaleColor;
 197:                      FemalePath.Stroke = FemaleColorDisabled;
 198:                      break;
 199:              }
 200:          }
 201:          #endregion
 202:      }
 203:  }

 Listing 2


Control in startup state Control has Female selected
Control in action




Series  - Create a UserControl with Silverlight 2.0 Beta x

Part II - Create a UserControl with SilverLight 2.0 Beta

Henry Cordes
My thoughts exactly...

Comments (3) -

Rob Leclerc | Reply

5/31/2009 1:56:23 PM #

I come from a Java background but for the past few months I've been programming with C# and Silverlight. I've been trying to get my head around Dependency Properties and how one "ought" to structure their code in Silverlight, but all the examples seem to be much more complex than they need to be, and so I feel that must be missing something.

For instance, most of the code above could have been written in about 40 lines with something like what you see below. On your follow up post you got into Dependency Properties and this tacked on another 30 lines, but I fail to see how this improved the code in anyway. It's longer, and more complex, and seemingly would be harder to maintain. As long as you have an event handler rigged up, subscribers can be notified of events as they happen and it seems like you are good to go?

I don't mean this to sarcastic, as I genuinely feel like I am missing something, but in many example using "advanced" Silverlight techniques, the complexity is a lot greater than it needs to be and I don't see where the nutritional value is.

public SolidColorBrush FemaleColor { get; set; }
public SolidColorBrush FemaleDisabled { get; set; }
public SolidColorBrush MaleColor { get; set; }
public SolidColorBrush MaleDisabled { get; set; }

public GenderChooser()
    FemaleColor = new SolidColorBrush(Color.FromArgb(255, 14, 27, 75);

private void MouseLeave(object sender, MouseEventArgs e)
   if(sender == FemalePath){
       FemalePath.Stroke = FemaleStrokeDisabled;
   else if(sender == MalePath){
       MalePath.Stroke = MaleStrokeDisabled;

5/31/2009 6:51:58 PM #

At the time I wrote this post, Silverlight 2 was in Beta. The reason why I did the second version on the post where the existence of Dependency Properties, as I write in the post, I had no kwnoledge of Silverlight or WPF at the time and the posts are my way of sharing my learning experience with everybody who is interested.
I really can imagine that it is overwhelming.

You are right in your suggestion that my code could be simplified by using the Mouseleave event on the control and checking in there what the sender is.
I don't think you are missing something here Smile
I am the first to agree, I have my limits and in this case I missed something, so thank you for pointing that out!

About Dependency Properties, I understand at first glance it looks a overengineered solution, but it is not.
You could choose to ignore them (as you point out), but than your controls are no longer functioning like Silverlight (or WPF) controls. You see a Dependency Property never really "has" a value…, its value depends on various external factors.  
I could try to explain everything, but I will point you to Josh Smith's blog, he wrote some excellent posts explaining Dependency Properties:

Rob Leclerc | Reply

6/1/2009 6:09:16 AM #

Agreed, all this can be a bit overwhelming. It seems like I am learning something new every ½ hour. The depth of C# and the patterns implemented by the Microsoft team really are staggering. Only today did I realize that dependency properties are injected for use in XAML.

Are very nice implementations of some sophisticated (but clean and succinct) Silverlight programming can be found in the BlackLight Media player (http://www.codeplex.com/blacklight) (See Instructions below). The MediaPlayer uses a dependency property to expose its “MediaSource” property so that you can add your custom MediaPlayer control to you Page.xaml with:

<MediaPlayer MediaSource=http://mymovie.wmv/>;

Finally I figured out how Silverlight controls like, TextBlock, were able to have attributes such as “Text”. Since the MediaPlayer wraps the MediaElement,there is no way to set the “Source” of the MediaElement in the Xaml of the MediaPlayer element without creating a dependency property (in this case “MediaSource”). Here MediaSource is essentially a proxy for setting the “Source” property of the MediaElement.

1.  Download “BlackLight Binaries.zip”,
2.  Unzip, then find the file /Blacklight.Silverlight.Controls/BlackLight.Controls.dll
3.  Place this in “Program Files/Microsoft SDKs/Silverlight/v2.0/Libraries/Client”
(So that it is with the rest of your silver light libraries)
4.  Now download the source code “Blacklight Source.zip”  and unzip
5.  Got to the directory /Blacklight Source/Blacklight.Controls/Blacklight.Controls/MediaPlayer/
6.  Create a new Silverlight Web application called MyApp and Drag and drop MediaPlayer.xaml and MediaPlayer.xaml.cs to the same location as the Page.xaml in MyApp (Or in a subdirectory of that same folder which we will name “Controls”)
7.  Open MediaPlayer.xaml and change the “x:Class” from its BlackLight name to: “MyApp.Controls.MediaPlayer” and then change the namespace of MediaPlayer.xaml.cs to “MyApp.Controls”
(Now your media player will just use the binaries from BlackLight.Controls and you can fork this player all you want) .
8.  Find your favorite .wmv movie and place it in ClientBin of your MyApp.Web directory.
9.  Open Page.xaml and add the element:
a.  Add to the UserControl:
xmlns:MyVideoPlayer="clr-namespace:MyApp.Controls" >

b.  Add within the Layout grid of Page.xaml

< MyVideoPlayer:MediaPlayer

10.  Find out what port your ASP.NET Development Server is going to run on so you can set the port properly in “MediaSource” which is a DependencyProperty of MediaPlayer (Just like “Text” is in TextBox”).  You can also set an address to another website hosting a .wmv  file.
11.  Now compile and run.

Add comment

  Country flag
  • Comment
  • Preview