Master C# Logo banner
Welcome to MasterCSharp.com - Master C#, the easy way... - by Saurabh Nandu

 


World Time Client Part2 : Building the User Controls

Add Comment
 

 
Download SDK
worldtimeclient-1.zip (37kb) Beta2

Introduction
In the previous part, I covered the installation and architecture of the World Time Client application. In this part I will show you how to create the DateTimeDisplayControl User Control which is used to display the world clocks. Please refer to the earlier article to understand the application architecture.

A) DateTimeDisplayControl - This control is used to create the UI for displaying the city/area name, date and current time. Since a different instance of this control will be used to display individual clocks I implement it as a User Control so that it becomes easier to use later on.

Building the User Control
1) Let's straight start with the tutorial, fire-up VS.NET Beta2, if its not already started and create a new Windows Control Library Project. Select the project name as DateTimeDisplayControl and enter the correct location where you want to create the project. Finally, click OK to let VS.NET create the new project for you and the default UserControl1.cs file will open up in the VS.NET Designer window. To give our source code file a new name, go to Solution Explorer window and select the file UserControl1.cs and press the F2 key and then rename the file to DateTimeDisplayControl.cs.
Next, select the User Control in the Designer window and press the F7 key to switch to Code window. In the Code window rename the namespace of the control from DateTimeDisplayControl to MasterCSharp.UserControl and also rename the class UserControl1 to DateTimeDisplayControl. Remember to rename the class constructor similarly!! Next add a private DateTime variable that will handle the control's date/time.
i.e Add the following line after the class definition.

private DateTime controlTime;


Figure 1: Create new Windows Control Library Project

2) Switch back to the Design window and select the User Control then press F4 key to pull-out the Properties window for the User Control. Change the following properties of the User Control from the Properties window. One thing you should note while creating Windows Forms that will be hosted from within Internet Explorer is that the Colors you use should not be set to Control Colors since they get rendered depending upon the colors of the HTML document hosting the Control and not upon the Operating System running the control! Does that make sense ?? ??

Property New Value
BackColor DarkKhaki
Name DateTimeDisplayControl
Size 130 , 120

3) Press Ctrl + Alt + X to pull-out the Toolbox window. Drag a Label control from the Toolbox and place it on the User Control. While the label is selected in the Design window press F4 key to bring-out the Properties window for the Label control. Change the following properties for the selected label control. Since this label will be used to display the city/area name we rename the variable as cityLabel.

 

Property New Value
BackColor MidnightBlue
BorderStyle FixedSingle
FlatStyle Flat
Font Veranda, 8.25, Bold (The font size in the Font Properties dialog is 8).
ForeColor Orange
Text (empty the textbox)
TextAlign MiddleCenter
Name cityLabel
Location 8, 8
Size 114, 24

4) Follow the above Step 3 and drag another Label on the User Control this label will be used to display the Date for the city/area. Change the following properties for this label from the Properties window.

 

Property New Value
BackColor MidnightBlue
BorderStyle FixedSingle
FlatStyle Flat
Font Veranda, 8.25, Bold (The font size in the Font Properties dialog is 8).
ForeColor Orange
Text (empty the textbox)
TextAlign MiddleCenter
Name dateLabel
Location 8, 40
Size 114, 40

5) Drag one more Label from the Toolbox as shown in Step 3, this label will be used to display the Time of the city/area. As usual pull-out the Properties window for this label and make the following changes.

 

Property New Value
BackColor MidnightBlue
BorderStyle FixedSingle
FlatStyle Flat
Font Veranda, 8.25, Bold (The font size in the Font Properties dialog is 8).
ForeColor Orange
Text (empty the textbox)
TextAlign MiddleCenter
Name timeLabel
Location 8, 88
Size 114, 24


Figure 2: DateTimeDisplayControl Design window.

6) This control will be self-sufficient to correctly update its date and time once they have been set by the parent. To regularly update the Control's UI at specific time spans we use the Timer component. Since we are creating a Windows Forms Control we use the Timer defined within the System.Windows.Forms namespace which has been optimized to work with GUI applications. The Timer raises the Tick event after the specified interval (in milliseconds, 1 Second = 1000 Milliseconds) has elapsed, you can handle this event and perform your task after the elapce of the specified time span.  Pull-Out the Toolbox window and under the Windows Forms tab search for the Timer component and drag it onto the Control. Remember that the Timer is a Component and not a Control, so does not have UI! VS.NET will update the Designer window and show the Timer Component below the Designer window. Select the Timer component and press the F4 key to bring out the Timer Properties. Change the following properties in the Properties window

 

Property New Value
Interval 1000
Name controlTimer

7) The above Step 6 completed the Controls/Component adding part of the User Control Project. Now I move on to adding code that makes the control tick! I hope you're ticking along too :).
Double-Click the controlTimer component from below the Designer window so that VS. Net automatically wires-up the Tick event of the component as well as it creates a empty event-handling method called controlTimer_Tick for you in the Code window. Since my control should update its date and time every second to emulate a real clock, in the above step I had setup the Timer component's Interval property to 1000 so that the Tick event is raised every second. In the event-handling method I just update the date and time labels to reflect the new date and time and of course we increment the controlTime variable (type DateTime)  by one second. Below is the complete implementation of the event-handling method.

 

private void controlTimer_Tick(object sender, System.EventArgs e)
{
  //Add a second to the time
  controlTime = controlTime.AddSeconds(1);
  //Display the Date and format it properly to fit the control space
  dateLabel.Text = controlTime.ToLongDateString().Replace(",","\r\n");
  //Display the time
  timeLabel.Text = controlTime.ToLongTimeString();
}

8) Next I add two more helper methods, StartTimer and StopTimer which as their name suggests start the control ticking and stop it from ticking respectively. Also the StopTimer method is used Dispose off the Timer component since its a costly resource and it should be disposed off as soon as its not needed. Below is the implementation of these methods along with a few helper properties which completes the implementation of this User Control.

 

public string City
{
  get
  {
    return cityLabel.Text;
  }
  set
  {
    cityLabel.Text = value;
  }
}

public string Date
{
  get
  {
    return controlTime.ToLongDateString();
  }
}

public string Time
{
  get
  {
    return controlTime.ToLongTimeString();
  }
}

public void StartTimer(DateTime newTime)
{
  //Set the Date Time
  this.controlTime = newTime;
  //Start the Timer
  this.controlTimer.Start();
}

public void StopTimer()
{
  this.controlTimer.Stop();
  //Release the resource
  this.controlTimer.Dispose();
}

9) Its a good idea to version the components from the beginning particularly when you want it to be downloaded dynamically from the Internet. So double-click the AssemblyInfo.cs file in the Solution Explorer to open the file in Code window and modify the following attributes as given below, feel free to remove the additional attributes that are not used.

 

[assembly: AssemblyTitle("DateTimeDisplayControl")]
[assembly: AssemblyDescription("This Control is used to display the City name, Date and Time")]
[assembly: AssemblyCompany("MasterCSharp.com")]
[assembly: AssemblyVersion("1.1.0.0")]

10) Once you have finished the above steps correctly the moment of truth arrives, press Ctrl+Shift+B to Build/Compile the project. If you ticked along synchronously then definitely you should see the message "Build: 1 succeeded, 0 failed, 0 skipped" in the Output window!
At this point if you wish you could build a small test Windows Forms application to test the functionality of this User Control, but I will refrain from explaining that since I still have a long way to go before completing this part...

Adding Toolbox Image
This part is a bit off-topic from my example ( its fun stuff :) ), but I have been overwhelmed with people asking me how they could display a custom image for their User Controls when its added in the VS.NET Toolbox window. So this section is the 'Users Demand' section, particularly in the case of my example it would be a bad idea to do this since it would increase the size of the assembly and I would like to keep that in control since the assembly is downloaded over the Internet!! In the actual implementation of this User Control you can skip this part if you like!

Just incase you are unaware, VS.NET's Toolbox is very customizable and you can freely add your own components and controls to it. To add a component/control right-click the Toolbox window and select Customize Toolbox from the context menu. The dialog that show's allows you to select a wide array of COM and .NET components that you could add to your Toolbox. If you would go to the .NET Framework Components tab, click Browse and select the DateTimeDisplayControll.dll User Control that we just compiled you will see a screen as shown below.


Figure 3: Customize Toolbox dialog

The summary of the selected assembly shown above (Figure 3) you can see that VS.NET has assigned a default icon () for your control/component, this same icon will be used for displaying your control/component in the Toolbox. This might not be a problem in all cases, but if you are a component/control vendor then definitely you would want to replace it with something that describes your controls/components more better!! As of Beta2 there is not much public documentation documenting this feature, but since MS has made its .NET Framework Classes extensible enough for any third-party tools creator to easily create tools like VS.NET without defining a specific API to get VS.NET like design-time support, its a matter of diving deeper into the Framework class documentation to find this functionality. I am summarizing my findings below! A special thanks to Mr. Kousay Alani who's question on the MS Newsgroup prompted me to dive deeper into this and the solution was found in 2 parts one by me, one by Mr. Kousay Alani.

1) The first step is to annotate the User Control class with the ToolboxBitmapAttribute from the System.Drawing namespace. One of the constructors of this class takes the Type to use while finding the bitmap to be used for displaying in the Toolbox. Following code snip shows how to annotate a class with this attribute. You will observe that I have used the typeof keyword and passed the Bitmap (System.Drawing namespace) Type to the attribute's constructor. This will remain constant for all your User Control implementations.

 

namespace MasterCSharp.UserControl
{

  [ToolboxBitmap(typeof(Bitmap))]
  public class DateTimeDisplayControl : System.Windows.Forms.UserControl
  {
    //class implementation....
  }
}

2) Now go to the Project menu and select Add New Item. Select Bitmap from the the Resources tab, rename the file as DateTimeDisplayControl.bmp and click OK. This seemed trivial, right?? Well this was one of the turns where many get stranded!! The file name of the Bitmap should correspond with the class name of the Control/Component that has been annotated by the ToolboxBitmap Attribute for this to work!! So be extra careful to see to it that you match the bitmap and class name when you are providing your custom implementation!

3) Now select the bitmap from the Bitmap Designer window and press the F4 key to pull-out the Properties window for the bitmap. Change the height and width property to 16 each and make sure that the Colors property is set to 16 Colors. This is because the preferable image attributes are 16x16x16 (Height, Width and Color). Although you could use a high color Bitmap also, but if you increase the size of the bitmap from 16x16 then is not rendered correctly in the VS.NET Toolbox. Once the properties have been set, feel free to design the Icon in the way you want, below is the design I have created very artistic, isn't it?? :). One more notable point is that the green color RGB (0,255,0) is used as a transparency color and is replaced by the control color in the VS.NET Toolbox.


Figure 4: Bitmap Design window

4) Go to the Solutions Explorer and select the DateTimeDisplayControl.bmp item from it and press the F4 key to bring out the Properties Explorer for the Bitmap file. Note that this is different from the Bitmap properties we worked on in the above step. From the Build Action property select Embed Resource, so that the bitmap file is embed into your assembly as a resource.

5) Finally, right-click on the DateTimeDisplayControl Project in the Solution Explorer and select Properties from the context menu. In the Properties dialog set the Default Namespace property to MasterCSharp.UserControl. In your custom implementation be sure you set the correct namespace of the class you have annotated with the ToolboxBitmap Attribute. The reason we need to do this is that VS.NET embeds all resources in the assembly by prefixing the Default Namespace followed by the filename of the resource. As you know, even though the namespace and class names appear different to us as programmers, the .NET Runtime always deals with the fully qualified class names i.e the namespace name followed by the class name. Hence while trying to find the correct bitmap to display for your control/component the .NET Runtime searches for the fully-qualified name of the bitmap that resembles the fully qualified name of the class that has been annotated with the ToolboxBitmap attribute, once found the correct bitmap is displayed. So be extra careful while dealing with this scenario. If you are not sure don't shy to use the service of the the ILDAM.exe tool. Run ILDASM and select the freshly compiled (after making all the above changes) DateTimeDisplayContol.dll assembly. Double-click on the Manifest item to see the Assembly Manifest of the assembly as shown in Figure 5. As you can see the bitmap resource name MasterCSharp.UserControl.DateTimeDisplayControl.bmp resembles the fully qualified name of our User Control and hence this will work!! If there is a mismatch then probably something needs to be fixed!


Figure 5: Assembly Manifest as seen in ILDASM

6) Just to be sure this works, go to the Toolbox window, right-click and  select Customize Toolbox from the context menu. In the Customize Toolbox dialog go to the .NET Framework Components tab and select the DateTimeDisplayControl.dll assembly that you just compiled (after making the above mentioned changes). You should see something like below. See the change in the Icon?? Neat, isn't it!


Figure 6: Customize Toolbox Dialog

B) WorldTimeService - This class actually contains the proxy class that will be used to communicate with the World Time Web service. Creating this assembly is nothing non-trivial, and I simple use the WSDL.exe tool provided along with the .NET Framework SDK to auto-generate the class for me. If you were a bit more picky about the file size, you could trim the source code and then manually compile the code to produce a more compact the assembly. I am going to take the easy way and simple compile the auto-generated class using the following commands at the command prompt (cmd.exe).
wsdl /n:MasterCSharp.WebService /out:WorldTimeService.cs http://www.MasterCSharp.com/live/TimeService/TimeService.asmx?WSDL

to create the source code file WorldTimeService.cs and then compile it with the following command
csc /t:library /out:MasterCSharp.WebService.WorldTimeService.dll WorldTimeService.cs

This will create the appropriate assembly which will be used later-on.

Conclusion
In this part I demonstrated the creation of the DateTimeDisplayControl in VS.NET and lastly I covered the trivial creation of the WorldTimeService proxy class. As an added bonus to this article I covered how to use the ToolboxBitmap Attribute to add icons to your controls/components. In the next articles in this series I will cover the creation of other two assemblies which are used in the World Time Client application.

Comments

Add Comment