Постигайте каждый подпункт в MenuStrip

Я хочу получить все SubItems из моего MenuStripТаким образом, я могу изменить их все сразу.

Я пробую что-то вроде следующего, но они не работают:

foreach (ToolStripMenuItem toolItem in menuStrip1.DropDownItems)
{
      //Do something with toolItem here
}

Может ли кто-нибудь помочь мне кодировать хороший foreach loop для получения всех SubMenuItems(DropDownItems) от MenuStrip?

РЕДАКТИРОВАТЬ сейчас пытается работать со следующими Recursive method:

private void SetToolStripItems(ToolStripItemCollection dropDownItems)
        {
            try
            {
                foreach (object obj in dropDownItems)
                {
                    if (obj.GetType().Equals(typeof(ToolStripMenuItem)))
                    {
                        ToolStripMenuItem subMenu = (ToolStripMenuItem)obj;

                        if (subMenu.HasDropDownItems)
                        {
                            SetToolStripItems(subMenu.DropDownItems);
                        }
                        else
                        {

                        }
                    }
                }
            }
            catch
            {

            }
        }

8 ответов

Решение

Попробуй это:

List<ToolStripMenuItem> allItems = new List<ToolStripMenuItem>();
foreach (ToolStripMenuItem toolItem in menuStrip.Items) 
{
    allItems.Add(toolItem);
    //add sub items
    allItems.AddRange(GetItems(toolItem));
}  
private IEnumerable<ToolStripMenuItem> GetItems(ToolStripMenuItem item) 
{
    foreach (ToolStripMenuItem dropDownItem in item.DropDownItems) 
    {
        if (dropDownItem.HasDropDownItems) 
        {
            foreach (ToolStripMenuItem subItem in GetItems(dropDownItem))
                yield return subItem;
        }
        yield return dropDownItem;
    }
}

Модификация ответа Вале. Разделители не будут аварийно завершать работу этой версии, и они также будут возвращены ( menuStripItems - это ToolStripItemCollection. То есть: this.MainMenuStrip.Items):

    /// <summary>
    /// Recursively get SubMenu Items. Includes Separators.
    /// </summary>
    /// <param name="item"></param>
    /// <returns></returns>
    private IEnumerable<ToolStripItem> GetItems(ToolStripItem item)
    {
        if (item is ToolStripMenuItem)
        {
            foreach (ToolStripItem tsi in (item as ToolStripMenuItem).DropDownItems)
            {
                if (tsi is ToolStripMenuItem)
                {
                    if ((tsi as ToolStripMenuItem).HasDropDownItems)
                    {
                        foreach (ToolStripItem subItem in GetItems((tsi as ToolStripMenuItem)))
                            yield return subItem;
                    }
                    yield return (tsi as ToolStripMenuItem);
                }
                else if (tsi is ToolStripSeparator)
                {
                    yield return (tsi as ToolStripSeparator);
                }
            }
        }
        else if (item is ToolStripSeparator)
        {
            yield return (item as ToolStripSeparator);
        }
    }

Заполните список:

    List<ToolStripItem> allItems = new List<ToolStripItem>();
    foreach (ToolStripItem toolItem in menuStripItems)
    {
       allItems.Add(toolItem);
       //add sub items
       allItems.AddRange(GetItems(toolItem));
    }

Зациклить список:

     foreach(ToolStripItem toolItem in allItems)
     {
          if(toolItem is ToolStripMenuItem)
          { 
             ToolStripMenuItem tsmi = (toolItem as ToolStripMenuItem);
             //Do something with it
          }
          else if(toolItem is ToolStripSeparator)
          {
             ToolStripSeparator tss = (toolItem as ToolStripSeparator);
             //Do something with it
          }
     } 

Кажется, вы не можете сделать это с прямым подходом "foreach". Я думаю, что я понял это.

List<ToolStripMenuItem> l = new List<ToolStripMenuItem> { };
        l.Add(menuItem1);
        l.Add(menuItem2);

        foreach (ToolStripMenuItem m in l)
        {
            m.Text = "YourTextHere";
        }

Добавление пунктов меню вручную в список является немного варварским, но использование 'foreach' или 'for' или других циклов дало мне ту же ошибку. кое-что о перечислении. Кажется, что они не могут сосчитать все элементы меню сами по себе:P С другой стороны, если у вас есть такие элементы, как разделители и другие элементы, это не совсем похоже на простой элемент меню, если поместить их все в один список и попытаться переименовать, поднять еще одну проблему.

Это для изменения текста, отображаемого в пунктах меню, но вы можете делать с ними абсолютно все, что хотите, используя этот метод.

Для.net 4.5 и выше я использовал это, чтобы получить выпадающие элементы для определенного набора инструментов.

foreach (var genreDropDownItem in this.toolStripMenuItem_AddNewShowGenre.DropDownItems)
    {
        if (genreDropDownItem is ToolStripMenuItem) //not a ToolStripSeparator
        {
            ToolStripDropDownItem genreItem = (genreDropDownItem as ToolStripDropDownItem);

            genreItem.Click += toolStripMenuItem_Genre_Click; //add the same click eventhandler to all dropdownitems of parent item this.toolStripMenuItem_AddNewShowGenre
        }
    }

Вы на самом деле ошиблись с типом, DropDownItems содержит коллекцию ToolStripItem не коллекция ToolStripMenuItem,

Попробуйте это вместо этого:

foreach (ToolStripItem toolItem in menuStrip1.DropDownItems)
{
    //do your stuff
}

Или в вашей функции:

private void SetToolStripItems(ToolStripItemCollection dropDownItems)
{
    foreach (ToolStripItem item in dropDownItems)
    {
        if (item.HasDropDownItems)
        {
            SetToolStripItems(item.DropDownItems);
        }
    }
}

Ниже приведен класс расширения, чтобы получить все ToolStripMenuItems. Преимущество здесь в том, что весь код находится в одном рекурсивном методе. Можно легко преобразовать это в универсальный метод, если нужны другие типы пунктов меню.

public static class ToolStripItemCollectionExt
{
    /// <summary>
    /// Recusively retrieves all menu items from the input collection
    /// </summary>
    public static IEnumerable<ToolStripMenuItem> GetAllMenuItems(this ToolStripItemCollection items)
    {
        var allItems = new List<ToolStripMenuItem>();
        foreach (var item in items.OfType<ToolStripMenuItem>())
        {
            allItems.Add(item);
            allItems.AddRange(GetAllMenuItems(item.DropDownItems));
        }
        return allItems;
    }
}

Обратите внимание, что "не работает" - это очень неэффективное описание. Вы должны опубликовать сообщение об ошибке или поведение.

foreach(var item in menuStrip1.Items)
{
 // do something with item... maybe recursively   
}

Здесь есть хорошее объяснение

Вот очень простое решение

foreach (Control Maincontralls in MDIParent1.ActiveForm.Controls) //start it from the form - in this example i started with MDI form
{
    if (Maincontralls.GetType() == typeof(MenuStrip)) // focus only for menu strip
    {
        MenuStrip ms = (MenuStrip)Maincontralls; //convert controller to the menue strip contraller type to access its unique properties

        foreach (ToolStripMenuItem subitem in ms.Items ) // access each items
        {

            if (subitem.Name == "loginToolStripMenuItem") subitem.Text = "Change text in loginToolStripMenuItem";
            //focus controller by its name and access its properties or whatever you wants
        }
        break; //break out the loop of controller of the form coz u don't need to go through other controllers
    }

}
Другие вопросы по тегам