Search code examples
vb.netwinformsuser-controlsresizewindows-forms-designer

How do I force a user control to have a fixed height already when dragging it from the toolbox onto a Windows form?


I want my newly designed user control to have a certain fixed height, right when being double-clicked within or drag'n'dropped from the toolbox onto its parent form.

For now, doing either does display the user control just in the height the user control's designer happened to have.

When starting the application with the constituent user control, the UC is displayed in the desired height, when stopping the app, it retains that height. This is due to the following code:

Private Sub UTest_Load(sender As Object, e As EventArgs) _
    Handles MyBase.Load

    ...
    Me.Height = 20
    ...
End Sub

Where do I need to initialize the UC's height, so that it is applied right when dragged from the toolbox?

Giving the UC's designer an initial fixed height is no option:the 20 pixels above are just an example, the correct height is variable and based on calculations. These calculations involve ParentForm.Font.


Solution

  • It sounds like you want to automatically compute the user control's size when it is placed on the WinForm design surface.

    When a control is added to the designer, its Site property is set. This property allows you to access various design services defined in the System.ComponentModel.Design Namespace. These services are accessed using the IServiceProvider.GetService Method. The Site property is of type ISite and ISite implements IServiceProvider.

    The service of interest is the IDesignerHost service as it allows you to obtain the root component (Control) that is being designed (in this case the Form).

    The following a simplistic way of overriding the usercontrol's Site property to gain access to the designer services.

    Imports System.ComponentModel.Design
    
    Public Class UCTest
       Public Overrides Property Site() As System.ComponentModel.ISite
          Get
             Return MyBase.Site
          End Get
          Set(ByVal value As System.ComponentModel.ISite)
             MyBase.Site = value
             If value IsNot Nothing Then SetDesignerSize()
          End Set
       End Property
    
       Private Sub SetDesignerSize()
          Dim host As IDesignerHost = DirectCast(Me.Site.GetService(GetType(IDesignerHost)), IDesignerHost)
          If host IsNot Nothing Then
             ' host.RootComponent is typically the form but can be another design surface like a usercontrol
             Dim parent As Control = TryCast(host.RootComponent, Control)
             If parent IsNot Nothing Then
                Dim frm As Form = parent.FindForm
                If frm IsNot Nothing Then
                   Me.Height = frm.Font.Height * 5
                   Me.Width = frm.Font.Height * 10
                End If
             End If
          End If
       End Sub
    End Class
    

    Edit: In response to comment seeking learning resources for custom control design-time features.

    Normally, I would tell a poster to research this them self, but this information is at best difficult to locate and I have never come across a definitive resource on the WinForm's designer features.

    However, here are some articles/blog posts that I have found useful. Keeping track of where these end up in MS's ever changing documentation system is a pain. So I advise that you make a personal copy of anything you find useful, because link will likely change or disappear completely.

    Building Windows Forms Controls and Components with Rich Design-Time Features (by Michael Weinhardt and Chris Sells), MSDN Magazine April 2003 Download

    Writing Custom Designers for .NET Components (by Shawn Burke)

    Walkthrough: Creating a Windows Forms Control That Takes Advantage of Visual Studio Design-Time Features

    Tailor Your Application by Building a Custom Forms Designer with .NET (by Sayed Y. Hashimi), MSDN Magazine December 2004 Download

    Leverage Custom Controls (By Stephen Perry) - Part1

    Leverage Custom Controls (By Stephen Perry) - Part2

    How to: Access Design-Time Services

    Walkthrough: Debugging Custom Windows Forms Controls at Design Time

    This last article has a section "Setting Up the Project for Design-Time Debugging" and is very important. For many design-time features, you can try to develop them in the project in which they are being used, but there are several pitfalls to doing so; the least of which is loss of proper debugging capabilities.

    The first is that you likely make Visual Studio become unstable at some point. This can be minimized by closing all active design surfaces before modifying the control's code and performing a Re-Build after modification, but eventually things will go wonky and you will have to restart Visual Studio.

    The second and more insidious issue is that I have found that certain types of designer code works differently when developed in-situ versus the recommended method. A custom TypeConverter will function perfectly using the proper technique and fail miserably when developed in-situ.