Search Wiki:

Background

In .NET Framework 4, a new Client Profile is introduced. This subset of the Framework is intended to be a more lightweight deployment for client applications that do not require server-side and design-time classes. When developing Windows Forms control libraries, it becomes necessary to separate the runtime code from the control designers in order to target the new Client Profile. If the assembly references classes that exist in the Full framework but not in the Client Profile, the project will not compile successfully. Custom control designers usually inherit from the System.Windows.Forms.Design.ControlDesigner class in System.Design.dll, which is not included in .Net Framework 4 Client Profile.

Architectural Guidance

Separating the implementation of the controls into runtime and design-time elements allows them to be compiled into separate assemblies. This guide will walk you through the steps of creating a Windows Forms control that can be used in the .NET Framework 4 Client Profile. You can also download and play with the sample solution.

1. Group your custom control source into 2 distinct parts: one for the runtime and one for design-time. The runtime part should contain only the implementation necessary at runtime. The control designers and supporting classes should be separated into a design-time grouping. This first step is typically straightforward as runtime files and design-time files are usually placed under different namespaces. In the sample solution, MySampleControl project represents runtime part and MySampleControlDesigner project represents design-time part. There is also a TestMySampleControl project that is used to test the sample control.

2. Create a project that contains only source for runtime features. If your project is targeting .Net Framework 3.5 or above, you should choose Client Profile as the target framework. This will allow you to tell at compilation if any references are present for classes that exist outside of the Client Profile.

3. Create a separate project that contains sources for design-time features. If your project is targeting .Net Framework 3.5 or above, you should choose Full Profile as the target framework. By doing so, you can add references to System.Design.dll or other design-time related assemblies later on. The design-time project can reference you runtime project that you created in step 2.

4. Compile those two projects. You may need to fix some “internal” access between the two projects as there are in different assemblies now. A strongly-typed DesignerAttribute will need to be replaced by a string as the attribute class itself does not exist in the Client Profile.

For example: DesignerAttribute specified with the following style:

    [Designer(typeof(MySampleControl.Design.MySampleControlDesigner))]
    public partial class MySampleControl : UserControl
should be changed to a “string” as in the following:

    [Designer("MySampleControl.Design.MySampleControlDesigner, MySampleControl.Design")]
    public partial class MySampleControl : UserControl
5. Compile both projects. Next copy the designer assembly into a folder and configure Visual Studio to search that path by creating a registry entry under HKLM\Software\Microsoft\.NETFramework\<version>\AssemblyFoldersEx, where <version> is the lowest framework version your designer assembly is compatible with. Note that your control projects target the earliest version of the Framework that your control will support. This is referred to as the minimum Framework version. A restart of Visual Studio is needed before the new search path can take effect.

6. Copy the runtime assembly into another folder; add your custom controls to Toolbox. This can be done either manually through “Choose Items…” dialog or programmatically with a Toolbox installation package. Please see this page Visual Studio Extension Deployment to find out a way to deploy your controls and designers.

7. Now, let's test if the separation works. Create a Windows Forms application that targets .Net Framework 4 Client Profile; drag and drop your control from Toolbox to Form designer and you will find that the control is successfully instantiated with its specified designer.

Notes

1. If your runtime and designer assembly are put in the same folder, Visual Studio might end up loading 2 copies of the same runtime assembly. This can cause some type conversion failures at design-time. To avoid this, place your runtime assembly and designer assembly into different folders.

2. When the designer assembly is not available (for example, when the controls from a runtime assembly have been added directly to the Toolbox without copying/installing the designer assembly), the designer specified for the control will not be found and the custom control will be added to Form designer just like a component. The ComponentDesigner is the default fallback when the custom control designer type is not successfully resolved. The sample solution demonstrates a workaround to achieve different fallback behavior. It uses the ITypeResolutionService interface to check the availability of the custom designer. If it is not available, it then uses a TypeDescriptor to replace the specified designer to a fallback designer dynamically. However, the more CustomTypeDescriptors are added, the bigger performance impact there would be to Visual Studio.
Last edited Apr 16 2010 at 1:53 AM  by Haoran, version 19
Updating...
Page view tracker