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.

