Click here to Skip to main content
Click here to Skip to main content

Automatically Enable/Disable Items with IExtenderProvider

, 18 Aug 2006
Rate this:
Please Sign up or sign in to vote.
Using Extender Provider to add properties to enable/disable items based on common classifications using IExtenderProvider
Sample Image - AutoEnableUI1.png

Introduction

Recently, I have been working on a project which requires that a large number of components be enabled/disabled based on what is open at the time. I wanted some options to be always enabled, some to be enabled only when a solution was open, and some enabled only when a child form was opened. Child forms could only be opened when the solution was open.

I experimented with various methods to control the updating, including using the Idle event to update each control based on flags or by adding attributes to each control and then using reflection to change them based on some events happening.

Both methods were really cumbersome and meant that whenever a new component was added, I had to edit the source to add the necessary UI handling. I couldn't believe that something so basic needed to have such a fragile solution.

It eventually dawned on me that there was a way in which this functionality could be added easily, and maintained through the property designer, rather than by manually editing the code. By using an Extender Provider, I was able to create a UI manager that managed the updating for me with minimum intervention.

Background

An excellent place to learn about Extender Providers is James Johnson's article, Getting to know IExtenderProvider.

Using the Code

The ExtenderProvider class that we are using here is simply a user control that implements the IExtenderProvider interface. For the purposes of the sample project, our code is going to enable/disable menu and toolbar items based on a solution being opened or closed, and child forms being opened/closed.

We start by providing an enumeration that indicates the level at which the relevant menu/toolbar item will be enabled:

public enum EnableType
{    
    Always,
    Solution,
    ChildForm,
} 

Menu items that have the type EnableType.Always set will always be enabled. EnableType.Solution, means that the menu item will only be enabled when the solution is open, and EnableType.ChildForm will only be enabled when the solution is open and there is at least one child form open.

We are going to provide the provider properties at the start of the UI manager definition like this:

[ProvideProperty("AutoEnable", typeof(Component))] 
public class UIManager : UserControl, IExtenderProvider     
{

As both toolbar buttons and menu items inherit from System.ComponentModel.Component, we can provide one property to control both.

The IExtenderProvider provides the CanExtend method which we use to let the forms designer know whether or not an item can be extended. This method passes in an object that we can interrogate to see if it matches the type in the ProvideProperty.

public bool CanExtend(object extendee)
{
    if (object is Component)
        return true;
    return false;
}

Because we are going to have multiple items hooked up to this extender, we will need to use a Hashtable.

private Hashtable _controls = new Hashtable();

Now, we are going to implement the methods to actually store the extended values. As our property is called AutoEnable, we need the methods SetAutoEnable and GetAutoEnable:

public EnableType GetAutoEnable(Component value)
{
    object ctrl = _controls[value];
    if (ctrl == null)
        return EnableType.Always;
    return (EnableType)ctrl;
}

public void SetAutoEnable(Component ctrl, EnableType value)
{
    _controls[ctrl] = value;
}

In GetAutoEnable, we check to see if we have added this menu or toolbar item into the hashtable already. If we haven't, we will return the default value where the item will always be enabled.

The last thing that we need to do is provide a method that will allow the forms that will host this object to actually enable/disable items.

public void Enable(EnableType type) 
{ 
    foreach (DictionaryEntry de in _controls) 
    { 
        EnableType tp = (EnableType)de.Value; 
        ToolBarButton button = de.Key as ToolBarButton; 
        if (button != null) 
        { 
            if (tp == EnableType.Always)
                Enable(button, true); 
            else if (type == EnableType.Solution && tp == EnableType.Solution) 
                Enable(button, true); 
            else if (type == EnableType.ChildForm && (
                            tp == EnableType.Solution || tp == EnableType.ChildForm)
                             ) 
                Enable(button, true); 
            else 
                Enable(button, false); 
        } 
        else 
        { 
            MenuItem btn = de.Key as MenuItem; 
            if (btn != null) 
            { 
                if (tp == EnableType.Always) 
                    Enable(btn, true); 
                else if (type == EnableType.Solution && tp == EnableType.Solution) 
                    Enable(btn, true); 
                else if (type == EnableType.ChildForm && (
                        tp == EnableType.Solution || tp == EnableType.ChildForm)
                        ) 
                    Enable(btn, true); 
                else 
                    Enable(btn, false); 
            } 
        } 
    } 
} 

private void Enable(ToolBarButton item, bool value) 
{ 
    item.Enabled = value; 
} 
private void Enable(MenuItem item, bool value) 
{ 
    item.Enabled = value; 
}

Now, compile the component and it is ready to be dropped onto a form.

When it is placed on a form, all of the controls that have descended from Component will automatically have an extended property called AutoEnable on UIManager1 with a default value of Always. If you rename the UIManager control to uiManager1, then the property name changes to AutoEnable on uiManager1.

Default property AutoEnable on uiManager1.
AutoEnable property set to default value.

We can now go through the toolbars/menu items and change the AutoEnable value to the appropriate value.

If we run the project at this stage, nothing is disabled. We still need to hook up the Enable method to respond to the various events.

In the Load event, we call:

uiManager1.Enable(EnableType.Always);

In the method to open the solution, we need to call:

uiManager1.Enable(EnableType.Solution);

In the method to close the solution, just call:

uiManager1.Enable(EnableType.Always);

In the method that opens the child forms, we need to call:

uiManager1.Enable(EnableType.ChildForm);

When the last child form has closed, just call:

uiManager1.Enable(EnableType.Solution);

Taking It Further

While we have only added one extended property to this control, it would be very easy to add extended properties to display text on the scrollbar based on the currently selected menu or toolbar item. The beauty of the extender provider model is that it is very flexible and very simple to use.

Conclusion

Using IExtenderProvider makes for a very easy way to control properties on a form. It is simple to implement, and provides a convenient way to add common functionality to a wide variety of controls.

History

  • 18th August 2006: Initial post
  • 20th August 2005: Minor amendment to text

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Pete O'Hanlon
CEO
United Kingdom United Kingdom
A developer for over 30 years, I've been lucky enough to write articles and applications for Code Project as well as the Intel Ultimate Coder - Going Perceptual challenge. I live in the North East of England with 2 wonderful daughters and a wonderful wife.
 
I am not the Stig, but I do wish I had Lotus Tuned Suspension.
Follow on   Twitter   Google+

Comments and Discussions

 
GeneralUseful PinmemberEd.Poore24-Aug-06 4:44 
GeneralRe: Useful PinmemberPete O'Hanlon24-Aug-06 9:13 
GeneralRe: Useful PinmemberEd.Poore24-Aug-06 21:53 
GeneralRe: Useful PinmemberPete O'Hanlon25-Aug-06 2:01 
GeneralRe: Useful PinmemberEd.Poore25-Aug-06 5:23 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140902.1 | Last Updated 18 Aug 2006
Article Copyright 2006 by Pete O'Hanlon
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid