views:

113

answers:

4

I devised the following code for displaying a control's Tag property on mouseover. The code works fine for standard controls such as Labels and TextBoxes but I cannot get it to work for my MenuItems (more specifically ToolStripMenuItems). Could y'all please take a look at my code and tell me what I did wrong? Thanks in advance!

public void Form1_Load(object sender, EventArgs e)

{

...

this.addEventsToAllComponents(this);

}

    private void addEventsToAllComponents(Component component)
{
  if (component is MenuItem)
  {
    MenuItem menuItem = component as MenuItem;
    menuItem.Select += new EventHandler(menuItem_Select);
  }
  else if (component is Control)
  {
    Control ctrl = component as Control;
    foreach (Control control in ctrl.Controls)
    {
      control.MouseEnter += new EventHandler(this.control_MouseEnter);
      control.MouseLeave += new EventHandler(this.control_MouseLeave);
      if (control.HasChildren)
        addEventsToAllComponents(control);
    }
  }
}

    private void menuItem_Select(object sender, EventArgs e)
{
  MenuItem menuItem = sender as MenuItem;

  if (menuItem.Tag.ToString().Length > 0)
    this.toolStripStatusLabel1.Text = menuItem.Tag.ToString();
}

private void control_MouseEnter(object sender, EventArgs e)
{
  Control control = sender as Control;

  if (control.Tag.ToString().Length > 0)
    this.toolStripStatusLabel1.Text = control.Tag.ToString();
}

private void control_MouseLeave(object sender, EventArgs e)
{
  if (this.toolStripStatusLabel1.Text.ToString().Length > 0)
    this.toolStripStatusLabel1.Text = "";
}
A: 

You don't have any code to handle ToolStripMenuItems - They are not derived from MenuItems, so your MenuItem-handling code won't do anything for them.

Aside: for readability, you might like to use string.IsNullOrEmpty(menuItem.Tag.ToString()) to test for empty/blank strings.

Jason Williams
Thanks for the suggestions; I'll work on the code a little more and see if I can get it to work right. I did not know about IsNullOrEmpty as I am new to C# but not programming in general. I will use it in the future from now on.
Blu Dragon
Changing the MenuItem to ToolStripMenuItem did not fix the problem. Any other suggestions?
Blu Dragon
A: 

You don't have the recursion set up for MenuItems that contain other menu items. So when it find a menuitem, it will only add the top level MenuItem, not it's children.

try adding:

foreach (MenuItem item in menuItem.MenuItems)
{
  item Select += new EventHandler(menuItem_Select);
  if (item.IsParent)
    addEventsToAllComponents(item);
}

in the section for handling MenuItems.

Alastair Pitts
Thanks for the tip. I did not use recursion for the MenuItems as I did not realize that MenuItems are nested but I'll work out the code for it.
Blu Dragon
Apparently, there is no isParent or has HasChildren for ToolStripMenuItems.
Blu Dragon
For ToolStripMenuItems, use: foreach (ToolStripMenuItem item in menuItem.DropDownItems). To test "IsParent", use (menuItem.DropDownItems.Count > 0)
Jason Williams
A: 

There are a few problems with your code.

1st. The Items of a MenuStrip are not children of the Item, so HasChildren will return false. Instead, they are in the Items collection of the MenuStrip. You need to handle a MenuStrip occurrence specially. Add the following code in your AddEvents... method below:

(snip...)
// old code                    
if (control.HasChildren)
    AddEventsToAllControls(control);
//add new code below
if (control is MenuStrip) {
    MenuStrip ms = control as MenuStrip;
    AddEventsToAllToolStripMenuitems(ms.Items);
}

And add the new method as follows:

private void AddEventsToAllToolStripMenuitems (ToolStripItemCollection items) {
    foreach (ToolStripItem tsi in items) {
        tsi.MouseEnter += new EventHandler(this.control_MouseEnter);
        tsi.MouseLeave += new EventHandler(this.control_MouseLeave);
        if (tsi is ToolStripMenuItem) {
            ToolStripMenuItem mi = tsi as ToolStripMenuItem;
            AddEventsToAllToolStripMenuitems(mi.DropDownItems);
        }
    }
}

2nd. ToolStripItem doesn't derive from Control, so in MouseEnter the sender as Control statement will fail (control will be null). Do something like this:

Control control = sender as Control;
if (control != null && control.Tag != null && control.Tag.ToString().Length > 0)
    this.toolStripStatusLabel1.Text = control.Tag.ToString();

ToolStripItem tsi = sender as ToolStripItem;
if (tsi != null && tsi.Tag != null && tsi.Tag.ToString().Length > 0)
    this.toolStripStatusLabel1.Text = tsi.Tag.ToString();

(I also added some null checks)

This should get you going.

M-Peror
Thanks M-Peror! That did the trick. You're the (wo)man!!!I guess I still have quite a lot to learn about when it comes to, VS08, C#, and WinForms.
Blu Dragon
I had to add the following to your code: " else if (control is ToolStrip) { ToolStrip ts = control as ToolStrip; AddEventsToAllToolStripItems(ts.Items); }".
Blu Dragon
A: 

Here is the revised code for AddEventsToAllComponents method:

private void addEventsToAllControls(Control ctrl)
{
  foreach (Control control in ctrl.Controls)
  {
    control.MouseEnter += new EventHandler(this.control_MouseEnter);
    control.MouseLeave += new EventHandler(this.control_MouseLeave);
    if (control.HasChildren)
      addEventsToAllControls(control);

    if (control is MenuStrip)
    {
      MenuStrip ms = control as MenuStrip;
      AddEventsToAllToolStripItems(ms.Items);
    }
    else if (control is ToolStrip)
    {
      ToolStrip ts = control as ToolStrip;
      AddEventsToAllToolStripItems(ts.Items);
    }
  }
}
Blu Dragon