Click here to Skip to main content
15,867,704 members
Articles / Desktop Programming / Windows Forms

Windows Ribbon for WinForms, Part 12 – CheckBox and ToggleButton

Rate me:
Please Sign up or sign in to vote.
5.00/5 (12 votes)
14 Mar 2010Ms-PL3 min read 25.2K   1.2K   18   1
In this article, I'll present how to use the ribbon check box and toggle button controls.

This series of CodeProject articles is based on a series of posts I've first published on my blog.

CheckBox and ToggleButton

In short, I've added support for CheckBox and ToggleButton ribbon controls. A new sample, named 10-CheckBox has been added to the project site. The result looks like this:

image

Using CheckBox and ToggleButton - Ribbon Markup

Commands and Views sections:

XML
<?xml version='1.0' encoding='utf-8'?>
<Application xmlns='http://schemas.microsoft.com/windows/2009/Ribbon'>
  <Application.Commands>

    <Command Name="cmdToggleButton"
             Id="1002"
             LabelTitle="Toggle Button">
      <Command.LargeImages>
        <Image>Res/Open32.bmp</Image>
      </Command.LargeImages>
      <Command.SmallImages>
        <Image>Res/Open16.bmp</Image>
      </Command.SmallImages>
    </Command>

    <Command Name="cmdCheckBox"
             Id="1003"
             LabelTitle="Check Box">
      <Command.LargeImages>
        <Image>Res/Save32.bmp</Image>
      </Command.LargeImages>
      <Command.SmallImages>
        <Image>Res/Save16.bmp</Image>
      </Command.SmallImages>
    </Command>

  </Application.Commands>

  <Application.Views>
    <Ribbon>
      <Ribbon.Tabs>
        <Tab>
          <Group>
            <ToggleButton CommandName="cmdToggleButton" />
          </Group>
          <Group CommandName="cmdGroupCheckBox">
            <CheckBox CommandName="cmdCheckBox" />
          </Group>
        </Tab>
      </Ribbon.Tabs>
    </Ribbon>
  </Application.Views>
</Application>

Using CheckBox and ToggleButton - Code-Behind

Initializing:

C#
private Ribbon _ribbon;
private RibbonToggleButton _toggleButton;
private RibbonCheckBox _checkBox;

public Form1()
{
  InitializeComponent();

  _ribbon = new Ribbon();
  _toggleButton = new RibbonToggleButton(_ribbon, 
                       (uint)RibbonMarkupCommands.cmdToggleButton);
  _checkBox = new RibbonLib.Controls.RibbonCheckBox(_ribbon, 
                   (uint)RibbonMarkupCommands.cmdCheckBox);

  _button.OnExecute += new OnExecuteEventHandler(_button_OnExecute);
}

Connect the IUICommandHandler implementation with the helper classes implementations: [If this the first time you see this, you should really check the previous posts..]

C#
public HRESULT Execute(uint commandId, RibbonLib.Interop.UI_ExecutionVerb verb, 
                        ref PropertyKey key, ref PropVariant currentValue, 
                        IUISimplePropertySet commandExecutionProperties)
{
     switch (commandId)
     {
         case (uint)RibbonMarkupCommands.cmdToggleButton:
             _toggleButton.Execute(verb, ref key, ref currentValue, 
                                   commandExecutionProperties);
             break;

         case (uint)RibbonMarkupCommands.cmdCheckBox:
             _checkBox.Execute(verb, ref key, ref currentValue, 
                               commandExecutionProperties);
             break;
     }

     return HRESULT.S_OK;
}

public HRESULT UpdateProperty(uint commandId, ref PropertyKey key, 
                               ref PropVariant currentValue, 
                               ref PropVariant newValue)
{
     switch (commandId)
     {
         case (uint)RibbonMarkupCommands.cmdToggleButton:
             _toggleButton.UpdateProperty(ref key, ref currentValue, ref newValue);
             break;

         case (uint)RibbonMarkupCommands.cmdCheckBox:
             _checkBox.UpdateProperty(ref key, ref currentValue, ref newValue);
             break;
     }

     return HRESULT.S_OK;
}

Update (18.11.2009): The updated version of the Ribbon class provides an implementation for IUICommandHandler, so the user doesn't need to implement the Execute and UpdateProperty methods anymore.

Get / Set checkbox status:

C#
void _button_OnExecute(ref PropertyKey key, ref PropVariant currentValue, 
           IUISimplePropertySet commandExecutionProperties)
{
  MessageBox.Show("checkbox check status is: " + _checkBox.BooleanValue.ToString());
}

Windows Ribbon for the WinForms Library - Internal Design Issues

The rest of this post is extremely boring. It discusses internal details of my ribbon library implementation. This doesn't change anything for the user of the library. Also, it has nothing to do with the checkbox feature.

Now that I'm the only one left, I can discuss some internal details of the library. I've just made a major refactoring of the ribbon library.

The ribbon library is composed of:

  • Windows Ribbon Framework API wrappers
  • Main ribbon class
  • Helper classes for different ribbon controls, such as Button, ComboBox, DropDownGallery etc.

In the old version of RibbonLib, the control helper classes had lots of duplicated code. For instance, each control that had images attached to it (LargeImage, SmallImage, ... properties) needed to handle those images in the same way (manipulating internal variables, notifying the parent ribbon that an image has invalidated etc.). Now, I don't know about you, but whenever I copy-paste code, I always get this strange feeling that something is wrong. So after several sample projects, I couldn't take it anymore, and decided to redesign this section.

What I've done was encapsulate common code in classes, so they can be reused in several controls without duplicating code.

So now, every ribbon control is composed of several property providers (like ImagePropertiesProvider and TooltipPropertiesProvider) and event providers (like ExeciteEventsProvider and PreviewEventsProvider).

Note: The following sentence is hard, but there is an example right after, so be strong.

Each provider component has its own interface which the using-control also implements by delegating the execution to the component.

For example, I have an ImagePropertiesProvider class that implements the interface IImagePropertiesProvider, which exposes four image properties (LargeImage, SmallImage, ..). In my Button helper class, I create a member variable of type ImagePropertiesProvider and make the Button class also implement IImagePropertiesProvider by calling the corresponding methods on the member variable.

This is one of those cases where multiple inheritance is really missing. As a substitute, what I did was use multiple inheritance of interfaces, aggregation, and delegation pattern. So the controls still have some duplicated code (the delegation code), but this code is really simple and has no logic in it.

Also, each ribbon control has Execute and UpdateProperty methods it needs to implement according to the properties and events it exposes. So I've made a general implementation which resides in theBaseRibbonControl class that searches the implementation of a property or event inside one of the registered providers, thus simplifying this code section in every control (now it doesn't exist, the simplest way I know).

The results of all these changes are:

  • Shorter code with less duplications.
  • Developing of new helper classes is extremely simple.
  • Cool class diagrams..
Property Providers Class Diagram

Image 2

Events Providers Class Diagram

Image 3

Ribbon Controls Class Diagram

Image 4

That's it for now.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)


Written By
Software Developer (Senior) Verint
Israel Israel
Arik Poznanski is a senior software developer at Verint. He completed two B.Sc. degrees in Mathematics & Computer Science, summa cum laude, from the Technion in Israel.

Arik has extensive knowledge and experience in many Microsoft technologies, including .NET with C#, WPF, Silverlight, WinForms, Interop, COM/ATL programming, C++ Win32 programming and reverse engineering (assembly, IL).

Comments and Discussions

 
-- No messages could be retrieved (timeout) --