Synchronizing the ToolBar
Usually, a toolbar duplicates functionality that is available in a window's menu. This can result in some rather tiresome state management code that has to carefully disable or enable menu items and the corresponding toolbar button at the same time. To simplify this process, you can create a customized menu class that automatically forwards its state to a linked toolbar control.
This custom control project is a little trickier than some of the previous examples. For one thing, it limits your ability to use the menu designer, because the custom menu items need to be created and added through code.
There's also more than one way to approach this problem. One possibility is to create a custom MenuItem class that stores a reference to a linked toolbar button.
public class LinkedMenuItem : MenuItem
{
public ToolBarButton LinkedButton;
// To save space, only one of the original constructors is used.
public LinkedMenuItem(string text) : base(text)
{ }
public bool Enabled
{
get
{
return base.Enabled;
}
set
{
base.Enabled = value;
if (LinkedButton != null)
{
LinkedButton.Enabled = value;
}
}
}
}
On the downside, this technique requires you to shadow the Enabled property (because it is not overridable), which is a sleight of hand that can further hamper design-time support for the menu. On the other hand, this is an extremely flexible approach. You could even replace LinkedButton with a collection that provides a whole series of controls that could be automatically enabled or disabled in the Enabled property procedure. Note that defensive programming is used to test the LinkedButton property before attempting to configure the referenced control, in case it has not been set.
The client program can create a linked menu using this class like this:
MainMenu menuMain = new MainMenu();
this.Menu = menuMain;
LinkedMenuItem menuItem1 = new LinkedMenuItem("File");
LinkedMenuItem menuItem2 = new LinkedMenuItem("Exit");
// This ToolBarButton is defined as a form-level variable.
menuItem2.LinkedButton = this.ToolBarButton2;
menuMain.MenuItems.Add(menuItem1);
menuItem1.MenuItems.Add(menuItem2);
// Both the ToolBarButton and MenuItem are disabled at once.
menuItem2.Enabled = false;
Another approach is to create a special MainMenu class. This class could provide an additional method that disables controls in tandem, without forcing you to observe this practice if you want to deal with MenuItem objects on your own. On the downside, you could forget to use the appropriate methods, and end up in an unsynchronized state. On the other hand, this approach provides you with more freedom. Figure 6-12 illustrates the difference.

Figure 6-12: Two ways to synchronize a menu and toolbar
The link is performed simply by setting the Tag property of the ToolBarItem to reference the appropriate MenuItem, but there are other possibilities. The Linked-MainMenu needs to iterate over all the buttons to find the matching one.
public class LinkedMainMenu : MainMenu
{
public ToolBar LinkedToolbar;
public void Enable(MenuItem item)
{
SetEnabled(true, item);
}
public void Disable(MenuItem item)
{
SetEnabled(false, item);
}
private void SetEnabled(bool state, MenuItem item)
{
item.Enabled = state;
if (LinkedToolbar != null)
{
foreach (ToolBarButton button in LinkedToolbar.Buttons)
{
if ((MenuItem)button.Tag == item)
{
button.Enabled = state;
}
}
}
}
}
And the client would follow this pattern:
LinkedMainMenu menuMain = new LinkedMainMenu();
menuMain.LinkedToolbar = myToolBar; // myToolBar is a form-level variable
this.Menu = menuMain;
MenuItem menuItem1 = new MenuItem("File");
MenuItem menuItem2 = new MenuItem("Exit");
menuMain.MenuItems.Add(menuItem1);
menuItem1.MenuItems.Add(menuItem2);
// (Create toolbar buttons as usual.)
ExitToolBarButton.Tag = menuItem2;
// Both the ToolBarButton and MenuItem are disabled at once.
menuMain.Disable(menuItem2);
In this case, I walked through two different approaches to creating a custom control. The following chapters won't have the luxury to be quite as discursive, but it's important that you start to think about all the possibilities for enhancing, customizing, and integrating controls. This is one of the most exciting aspects of .NET user interface programming.