Adding Designer Support to the .NET Compact Framework DateTimePicker Control

.NET Compact Framework 1.0
 

Jim Wilson
JW Hedgehog, Inc.

October 2003

Applies to
   Microsoft® .NET Compact Framework 1.0
   Microsoft® Visual Studio® .NET 2003

Summary: Gain technical insight into the .NET Compact Framework date selection control, the DateTimePicker control. How to create the control assemblies and install the DateTimePicker control are described in detail. (9 printed pages)


Download DateTimePickerDesignTimeSampleSetup.exe.

Contents

Introduction
Overview
Creating the Control Assemblies
Installing the DateTimePicker Control
Conclusion

Introduction

The DateTimePicker control is a .NET Compact Framework date selection control written entirely in managed code. As shown in Figure 1, the DateTimePicker provides an easy and convenient way to enter dates into Pocket PC applications by allowing users to choose the date from a pop-up calendar.

Figure 1. The DateTimePicker control in action.

Unlike the desktop .NET Framework, .NET Compact Framework controls do not automatically support Microsoft Visual Studio .NET designer integration. The DateTimePicker is no exception. This article walks through the process of adding Visual Studio .NET designer support to the DateTimePicker.

Note   The original DateTimePicker control was written by Ralph Aversen of Vertigo Software, Inc. The original source code is contained within a Pocket PC Windows Application project, DateTimeSample. To read his discussion of building the original DateTimePicker, see Microsoft .NET Compact Framework DateTimePicker Control.

Overview

Modifying the original DateTimePicker to support Visual Studio .NET designer integration requires creating a new Visual Studio .NET Solution, DateTimePickerControl. The DateTimePickerControl solution contains three projects.

Project Description
DateTimePickerControl Smart Device Class Library project targeting the Pocket PC. Creates the run-time control. This is the only project containing source code.
DateTimePickerControl.Design C++ Makefile project. Creates the Visual Studio .NET design-time control. Contains no C++ code.
DateTimePickerControl.Deployment Setup project. Creates a Windows Installer file to install the run-time and design-time assemblies.
Note   The original DateTimePicker control example is available in both C# and VB .NET however this version is available only in C#. As of this writing, .NET Compact Framework controls written in VB .NET cannot be integrated into the Visual Studio .NET designer. The DateTimePicker control is, of course, usable by both C# and VB .NET clients.

As you can see by the project list, .NET Compact Framework controls supporting the Visual Studio .NET designer require two separate assemblies. The assembly created by the DateTimePickerControl project is a regular .NET Compact Framework library assembly. The assembly created by the DateTimePickerControl.Design project is a desktop assembly containing the additional metadata required to support the Visual Studio .NET designer. Using separate run-time and design-time assemblies avoids increasing a controls run-time footprint to carry information required only at design-time. The run-time control carries no design-time information and is exactly the same with or without the control supporting the designer.

The DateTimePickerControl.Deployment Setup project is provided as a convenience to simplify assembly installation.

Once installed, the DateTimePicker can be used from the Visual Studio .NET toolbox just as easily as the built-in .NET Compact Framework controls with complete support for drag-and-drop positioning and setting properties through the Property window as shown in figure 2.

Figure 2. DateTimePicker in Visual Studio .NET

Creating the Control Assemblies

The first step in supporting the designer is to put the DateTimePicker into a class library. This is done by simply adding the DateTimePicker.cs source file from the original DateTimeSample Windows application project to the DateTimePickerControl class library project. Of the solution’s three projects, DateTimePickerControl is the only one containing source code. As shown in Figure 3, it contains the DateTimePicker.cs source file along with the standard AssemblyInfo.cs.

Although part of the DateTimePickerControl project, theDateTimePicker.cs and AssemblyInfo.cs source files are also used by DateTimePickerControl.Design. As a Makefile project, DateTimePickerControl.Design simply executes the C# command-line compiler, CSC.exe, to build the design-time assembly from the DateTimePickerControl source code files. Rather than reference the regular .NET Compact Framework library assemblies, designer versions of the .NET Compact Framework library assemblies (along with desktop library assemblies) are referenced to create a designer-ready, desktop version of the assembly. In addition to referencing different assemblies, the conditional compilation constant "NETCFDESIGNTIME " is defined. By defining the constant only in the DateTimePickerControl.Design build, it is possible to place code in the source files that

will only be compiled into the design-time assembly.

Figure 3. Solution Projects

The Relationship Between the Run-Time and Design-Time Assemblies

As it stands, DateTimePickerControl and DateTimePickerControl.Design are two unrelated assemblies compiled from the same source code. If the design-time assembly was added to the Visual Studio .NET toolbox, Visual Studio .NET would not know how to locate the corresponding run-time assembly. To create a relationship, between the assemblies, the "RuntimeAssembly " attribute is added to the AssemblyInfo.cs source file.

#if NETCFDESIGNTIME
[assembly: System.CF.Design.RuntimeAssembly(
  "DateTimePickerControl, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null ")]
#endif 

By enclosing the RuntimeAssembly attribute in the "NETCFDESIGNTIME " conditional compilation block, the attribute is compiled only into the design-time assembly created by DateTimePickerControl.Design. The RuntimeAssembly attribute tells Visual Studio .NET that DateTimePickerControl is the real assembly and that DateTimePickerControl.Design is used only at design-time.

Properties

As with the built-in controls, DateTimePicker properties can be edited in the Visual Studio .NET Property window. By default all public properties appear in the Property window. Adding attributes to the properties tells Visual Studio .NET just how each property should be displayed.

#if NETCFDESIGNTIME
  [System.ComponentModel.Category("Appearance")]
  [System.ComponentModel.DefaultValue("1/1/2003 ")]
  [System.ComponentModel.Description("The value of the control.")]
#endif
  public DateTime Value
  { ... } 

With these attributes, the Value property appears as shown in Figure 4. The attributes indicate that the property should be in the "Appearance " category of the property window with the default value set to "1/1/2003 ". When the Value property is selected, "The value of the control " appears in the Description window.

Figure 4. The Value property in the Visual Studio .NET Property window.

The DateTimePicker Text property creates a special challenge as it is a string wrapper over the Value property which is a DateTime. Strings assigned to the Text property are parsed by the DateTime.Parse method with the resulting date stored in the Value property meaning that any string assigned to the Text property must be a valid date. By default, Visual Studio .NET initially sets a control’s Text property to be the control’s name; for example:

dateTimePicker1.Text = "dateTimePicker1 ".

"dateTimePicker1 " is not a valid date string and will cause the Text property to throw an exception when the control is placed on the form. Visual Studio .NET exhibits this behavior even if the Text property is marked with the DefaultValue attribute containing a valid date.

To avoid this problem, the Text property is marked with the DesignerSerializationVisibility attribute. Setting the attribute value to Hidden tells Visual Studio .NET to not generate the code to assign a value to the property. The Text property is also marked with the Browsable attribute set to false so that it does not appear in the Property window. Having the Text property appear in the Property window is redundant – it is just a wrapper over the Value property which is already in the Property window.

#if NETCFDESIGNTIME
  [System.ComponentModel.Browsable(false)]
  [System.ComponentModel.DesignerSerializationVisibility(
      System.ComponentModel.DesignerSerializationVisibility.Hidden)]
#endif
  public override String Text
  { ... }

Designer Display

Visual Studio .NET uses the DateTimePicker normal painting behavior to display the control in the designer so no special painting work is required. The only consideration is resizing. When the control is resized it doesn’t automatically repaint the whole control, so it can end up looking like figure 5.

Figure 5. Resized DateTimePicker being improperly redrawn.

The problem is easily corrected by invalidating the control when it is resized.

protected override void OnResize(EventArgs e)
{
  base.OnResize (e);
  this.Invalidate();
}

Project Configuration Details

DateTimePickerControl Project

The DateTimePickerControl Project is a standard Smart Device project configured to build a class library targeting the Pocket PC. All project configuration options are left at their default settings.

DateTimePickerControl.Design Project

The DateTimePickerControl.Design Project is a C++ Makefile project containing no C++ code. Makefile projects are useful when the build process requires a command line to be executed. In the case of DateTimePickerControl.Design, the command line is the C# compiler, CSC.exe.

Compiler Options

The project is configured to execute the C# compiler with the following options.

Option Description
/noconfig Do not link in the default assemblies.
/define:NETCFDESIGNTIME Include code in NETCFDESIGNTIME conditional compilation blocks.
/out:$(TargetPath) Name the resulting assembly as defined in the project options. The "TargetPath " is configured by the project "Output " option, which is set to "DateTimePickerControl.Design.dll ".
/target:library Create a library assembly.
$(SolutionDir)DateTimePicker.cs
$(SolutionDir)AssemblyInfo.cs
Compile the DateTimePicker.cs and AssemblyInfo.cs files located in the DateTimePickerControl directory.
/resource:$(ProjectDir)
DateTimePickerControl.DateTimePicker.bmp
Embed the bitmap into the resulting assembly. The bitmap is located in the current project directory.
/nowarn:1595 Ignore warning 1595. Warning 1595 is generated when a type is defined in more then one of the referenced assemblies.

Referenced Library Assemblies

The compiler references .NET Compact Framework specific designer assemblies in addition to the regular desktop assemblies. The .NET Compact Framework designer assemblies are located in "<Visual Studio .NET Install Directory>CompactFrameworkSDK\v1.0.5000\Windows CE\Designer ".

Caution   The order in which the assemblies are referenced critical. The .NET Compact Framework designer assemblies must be referenced prior to the standard desktop assemblies (as some of the types required by the design-time control are redundantly defined appearing in both the .NET Compact Framework designer assemblies and the desktop assemblies). The linker uses the definition it finds first.
The redundant type definitions are the reason that .NET Compact Framework design-time assemblies cannot be created using VB .NET. C# considers multiple type definitions only a warning whereas VB .NET considers them an error and will not generate the assembly.

Resource Files

The only file contained in the project is a bitmap. As shown in Figure 6, the bitmap is used by Visual Studio .NET to display the DateTimePicker in the toolbox. Visual Studio .NET requires that the bitmap be 16 x 16 pixels and have the same name (including namespace) as the control, DateTimePickerControl.DateTimePicker.bmp. If no bitmap is provided, a spinning gear is used as in the case of the DataGrid in Figure 6.

Figure 6. DateTimePicker in the Visual Studio .NET Toolbox

Installing the DateTimePicker Control

Once the assemblies are built, they need to be installed. Installing the DateTimePicker is just a matter of copying the assemblies to the appropriate directories. The run-time assembly file, DateTimePickerControl.dll is copied to <Visual Studio .NET Install Directory>CompactFrameworkSDK\v1.0.5000\Windows CE. The design-time assembly file, DateTimePickerControl.Design.dll is copied to <Visual Studio .NET Install Directory>CompactFrameworkSDK\v1.0.5000\Windows CE\Designer.

To simplify installing and distributing the assemblies, the DateTimePickerControl solution includes a deployment project, DateTimePickerControl.Deployment. This is a Setup project that produces a Microsoft Installer file (.msi) to automate the copy process.

Adding DateTimePicker to the Visual Studio .NET Toolbox

Once the assemblies are in the appropriate directories, the DateTimePicker can be added to the Visual Studio .NET toolbox by doing the following:

  • Right-click on the Visual Studio .NET Toolbox and choose "Add/Remove Items ".
  • On the "Customize Toolbox " dialog, Click "Browse…".
  • Navigate to <Visual Studio .NET Install Directory>CompactFrameworkSDK\v1.0.5000\Windows CE\Design and select "DateTimePickerControl.Design.dll ".
  • On the "Open " dialog, click "Open ".
  • On the "Customize Toolbox " dialog, click "OK ".

The DateTimePicker should appear in the toolbox ready to use.

Conclusion

With the process complete, the DateTimePicker is as easy to use as any of the built-in .NET Compact Framework controls. It supports drag-and-drop positioning with the properties categorized and editable in the Property window with each showing the appropriate description.

The DateTimePicker has been integrated into the Visual Studio .NET designer just by adding a few attributes to the source code and executing the appropriate command-line compile to build a designer version of the assembly. Using this same procedure, your .NET Compact Framework custom controls can be integrated into the Visual Studio .NET designer to give them a professional appearance and make them easier to use.

Show: