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();
}
}
Comments