Library tutorials & articles

Collection Controls with Rich Design Time Support

Wrapping Up

Removing Buttons

This is another question of playing nicely with the designers. We will be writing the code to go in the OnComponentRemoving function in our designer. We need to handle two things in here. Firstly, the user removing the main control. When this happens we need to destroy all the buttons that are on the design surface. Secondly, when the user removes a button by selecting it and pressing delete. We need to remove it from the Button collection when this happens. Again, any changes we make to anything need to be wrapped in OnComponentChanging and OnComponentChanged calls.

VB.NET

Private Sub OnComponentRemoving(ByVal sender As Object, ByVal e As ComponentEventArgs)
    Dim c As IComponentChangeService = DirectCast(GetService(GetType _
    (IComponentChangeService)), IComponentChangeService)
    Dim button As ColourButton
    Dim h As IDesignerHost = DirectCast(GetService(GetType(IDesignerHost)), IDesignerHost)
    Dim i As Integer
    'If the user is removing a button
    If TypeOf e.Component Is ColourButton Then
        button = DirectCast(e.Component, ColourButton)
        If MyControl.Buttons.Contains(button) Then
            c.OnComponentChanging(MyControl, Nothing)
            MyControl.Buttons.Remove(button)
            c.OnComponentChanged(MyControl, Nothing, Nothing, Nothing)
            Return
        End If
    End If
    'If the user is removing the control itself
    If e.Component Is MyControl Then
        For i = MyControl.Buttons.Count - 1 To 0 Step -1
            button = MyControl.Buttons(i)
            c.OnComponentChanging(MyControl, Nothing)
            MyControl.Buttons.Remove(button)
            h.DestroyComponent(button)
            c.OnComponentChanged(MyControl, Nothing, Nothing, Nothing)
        Next
    End If
End Sub

C#

private void OnComponentRemoving(object sender, ComponentEventArgs e)
{
    IComponentChangeService c = (IComponentChangeService)
    GetService(typeof(IComponentChangeService));
    ColourButton button;
    IDesignerHost h = (IDesignerHost) GetService(typeof(IDesignerHost));
    int i;
    // If the user is removing a button
    if (e.Component is ColourButton)
    {
        button = (ColourButton) e.Component;
        if (MyControl.Buttons.Contains(button))
        {
            c.OnComponentChanging(MyControl, null);
            MyControl.Buttons.Remove(button);
            c.OnComponentChanged(MyControl, null, null, null);
            return;
        }
    }
    // If the user is removing the control itself
    if (e.Component == MyControl)
    {
        for (i = MyControl.Buttons.Count - 1; i >= 0; i--)
        {
            button = MyControl.Buttons[i];
            c.OnComponentChanging(MyControl, null);
            MyControl.Buttons.Remove(button);
            h.DestroyComponent(button);
            c.OnComponentChanged(MyControl, null, null, null);
        }
    }
}

Now that we've added that code, the user can delete buttons visually as they would delete any other control or component on the design surface. Also, Undo and Redo now work when adding buttons.

Conclusion

We have created the basics of a toolbar control with rich design time support. Adding more properties to the buttons is easy compared to the code we've had to write to enable this support. I hope you've found this article useful, it has certainly demonstrated a lot of the techniques you'll use when writing both design time and runtime code. The toolbar doesn't actually do anything at run time except sit there and look pretty, but we already have the elements in place to add support for mouseovers and a ButtonClick event.

I have provided a solution with both a VB and C# project, which are functionally identical.

Comments

  1. 30 Jan 2009 at 17:58
    Nice article, I'm writing a toolstrip type control and this helped me figure out how to remove the child component on deletion. I liked how you selected components in the control on mouse down, however, I had done it differently. Because my control was written in the compact framework, with the designer code being in the full framework. I couldn't select my component in the control code itself by checking for design mode. Therefore, I handled wndproc: protected override void WndProc(ref System.Windows.Forms.Message m) { // left mouse down if (m.Msg == WM_LBUTTONDOWN) { int data = m.LParam.ToInt32(); int y = (int)(data & 0xFFFF0000) >> 16; int x = (int)(data & 0x0000FFFF); Point pt = new Point(x, y); OptionStrip strip = (Control as OptionStrip); clickItem = strip.GetItemAt(pt); if (clickItem != null) return; } else if (m.Msg == WM_LBUTTONUP && clickItem != null) { int data = m.LParam.ToInt32(); int y = (int)(data & 0xFFFF0000) >> 16; int x = (int)(data & 0x0000FFFF); Point pt = new Point(x, y); OptionStrip strip = (Control as OptionStrip); if (strip.GetItemAt(pt).Equals(clickItem)) { ISelectionService ss = (ISelectionService)GetService(typeof(ISelectionService)); ArrayList list = new ArrayList(); list.Add(clickItem); ss.SetSelectedComponents(list, SelectionTypes.Primary); } clickItem = null; return; } I think your solution is simpler, and probably more solid, but this is necessary as the ISelectionService does not exist in the compact framework. However, it does seperate design time code.
  2. 23 May 2007 at 19:35

    GREAT ARTICLE¡¡¡  thank you very, very much, now i can finish my own control. 

    I could not save my own custom class object, NOW I CAN.

  3. 19 Mar 2007 at 09:08
    I've tried to compile the code I've downloaded but at run-time (placed in a form on another project) I don't see the buttons I've created at deign-time..
  4. 17 Jan 2007 at 19:46
    Is it safe to assume value (of complex type) of a property has instance descriptor converter for every component/control you dropped on design surface.

    Regards
    Phani




  5. 01 Jan 1999 at 00:00

    This thread is for discussions of Collection Controls with Rich Design Time Support.

Leave a comment

Sign in or Join us (it's free).

Tim Dawson

Related discussion

Related podcasts

  • More jQuery in ASP.NET

    In this episode Chris Brandsma, Rick Strahl, Dave Ward, Bertrand Le Roy, and Scott Koon conclude their discussion of Microsoft's jQuery in ASP.NET announcement1.This episode of the Alt.NET Podcast is brought to you by LLBLGen Pro, the most mature O/R mapper and code generator out there.Are ...

Events coming up

  • Dec 9

    GL.net Group Meeting - December 2009

    Gloucester, United Kingdom

    The beginning of this year holiday season will belong to mocks. Ronnie and Stephen will take us for a tour around exciting world of unit testing.

We'd love to hear what you think! Submit ideas or give us feedback