Collection Controls with Rich Design Time Support

Starting Off

I won't put all the code in to this article, because it would just get cluttered. Instead I will paste the important bits, and attempt to describe the rest. I will be developing the control in both VB and C# as I write, and the resultant solution will be available for download at the end.

First things first, we add the new usercontrol to our project. As we don't want our drawing to flicker, we use the protected SetStyle function in the constructor to turn on the DoubleBuffer and AllPaintingInWmPaint styles. These two go hand in hand. We also define the CalculateLayout function, which we will be calling from the collection and when the control is resized.

Next comes defining the subitem class, and the strongly-typed collection class which we'll use to contain the buttons. At this point we add the Buttons property to the main control, which exposes a private instance of this collection, instantiated in the main control's constructor. The ColourButton has an internal Bounds member of type Rectangle, which will hold the position of the button in the control.

For simplicity, our collection will only implement the Add and Remove functions, and the indexer. Normally you would add a few more strongly-typed helper functions to it, such as IndexOf. The constructor of the collection is internal and takes an instance of the main control as a parameter. This is so that this instance can be passed on to buttons as they are added, because when the user changes the colour of a button it needs to signal that a redraw is needed. Here is the code for the ColourButton and ColourButtonCollection classes:

VB.NET

Public Class ColourButton
    Inherits Component
    Private _Colour As Color = Color.White
    Friend Control As CollectionControl = Nothing
    Friend Bounds As Rectangle
    <DefaultValue(GetType(Color), "White")> _
    Public Property Colour() As Color
        Get
            Return _Colour
        End Get
        Set(ByVal Value As Color)
            _Colour = Value
            If Not Control Is Nothing Then Control.Invalidate()
        End Set
    End Property
End Class
Public Class ColourButtonCollection
    Inherits CollectionBase
    Private Control As CollectionControl
    Friend Sub New(ByVal Control As CollectionControl)
        Me.Control = Control
    End Sub
    Default Public ReadOnly Property Item(ByVal Index As Integer) As ColourButton
        Get
            Return DirectCast(List(Index), ColourButton)
        End Get
    End Property
    Public Function Contains(ByVal Button As ColourButton) As Boolean
        Return List.Contains(Button)
    End Function
    Public Function Add(ByVal Button As ColourButton) As Integer
        Dim i As Integer
        i = List.Add(Button)
        Button.Control = Control
        Control.CalculateLayout()
        Return i
    End Function
    Public Sub Remove(ByVal Button As ColourButton)
        List.Remove(Button)
        Button.Control = Nothing
        Control.CalculateLayout()
    End Sub
End Class

C#

public class ColourButton : Component
{
    private Color _Colour = Color.White;
    internal CollectionControl Control = null;
    internal Rectangle Bounds;
    public Color Colour
    {
        get
        {
            return _Colour;
        }
        set
        {
            _Colour = value;
            if (Control != null)
                Control.Invalidate();
        }
    }
}
public class ColourButtonCollection : CollectionBase
{
    private CollectionControl Control;
    internal ColourButtonCollection(CollectionControl Control)
    {
        this.Control = Control;
    }
    public ColourButton this[int Index]
    {
        get
        {
            return (ColourButton) List[Index];
        }
    }
    public bool Contains(ColourButton Button)
    {
        return List.Contains(Button);
    }
    public int Add(ColourButton Button)
    {
        int i;
        i = List.Add(Button);
        Button.Control = Control;
        Control.CalculateLayout();
        return i;
    }
    public void Remove(ColourButton Button)
    {
        List.Remove(Button);
        Button.Control = null;
        Control.CalculateLayout();
    }
}

You might also like...

Comments

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“Before software should be reusable, it should be usable.” - Ralph Johnson