Скрыть лишний ToolStripSeparator в меню - PullRequest
0 голосов
/ 16 ноября 2018

У меня есть ContextMenuStrip элемент управления с несколькими пунктами меню A, B, C, D, E и разделителями до и после пункта C.

enter image description here

Во время выполнения я динамически решаю в событии Opening, показывать ли пункт меню C на основе некоторых условий.

private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
{
    toolStripMenuItemC.Visible = SomeCondition;
}

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

enter image description here

Существует ли какой-либо встроенный механизм для автоматического объединения нескольких последовательных разделителей меню в один?Например, среда VCL в Delphi имеет для этого свойство TPopupMenu.AutoLineReduction.


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

Я ищу общий способ использования любого меню, которое работает без знания конкретных пунктов меню.Я бы предпочел какой-то способ, который уже включен в WinForms из коробки, но вы также можете ответить с помощью собственной функции инструмента, чтобы очистить разделители в меню.

Ответы [ 2 ]

0 голосов
/ 16 ноября 2018

Попробуйте, это работает по-другому, показывая или скрывая ToolStripMenuItem и ToolStripSeparator на основе относительного положения ToolStripMenuItem, чтобы скрыть:

ToolStripSeparators отображаются / скрываются, когда:

  1. Меню является последним, а предыдущий элемент является ToolStripSeparator
  2. Меню является первым, а следующее является ToolStripSeparator
  3. Меню предшествует и сопровождается ToolStripSeparator

Вызов метода: ShowHideMenuItem([ParentMenu], [ToolStripMenuItem], [true|false])

ShowHideMenuItem(ToolStripMenuItem1, ToolStripMenuItem5, true);

private void ShowHideMenuItem(ToolStripMenuItem ParentMenu, ToolStripMenuItem MenuItem, bool ShowOrHide)
{
    if (!ParentMenu.HasDropDownItems) return;
    int itemIndex = ParentMenu.DropDownItems.IndexOf(MenuItem);

    if (ParentMenu.DropDownItems.Count > 1)
    {
        if (itemIndex == 0 &&
            ParentMenu.DropDownItems[itemIndex + 1].GetType() == typeof(ToolStripSeparator)) {
            ParentMenu.DropDownItems[itemIndex + 1].Visible = ShowOrHide;
        }
        else if (itemIndex == ParentMenu.DropDownItems.Count - 1 &&
                    ParentMenu.DropDownItems[itemIndex - 1].GetType() == typeof(ToolStripSeparator)) {
            ParentMenu.DropDownItems[itemIndex - 1].Visible = ShowOrHide;
        }
        else if (ParentMenu.DropDownItems[itemIndex + 1].GetType() == typeof(ToolStripSeparator) &&
                    ParentMenu.DropDownItems[itemIndex - 1].GetType() == typeof(ToolStripSeparator)) {
            ParentMenu.DropDownItems[itemIndex + 1].Visible = ShowOrHide;
            ParentMenu.DropDownItems[itemIndex - 1].Visible = ShowOrHide;
        }
    }
    MenuItem.Visible = ShowOrHide;
}
0 голосов
/ 16 ноября 2018

Поскольку я не нашел встроенного способа сделать это в WinForms, я написал эту служебную функцию:

public static class ToolStripExtensions
{
    /// <summary>
    /// Automatically show/hide separator in toolstrips (Menus, toolbars, etc).
    /// This will hide / show separators based on the other toolstripitems in the collections.
    /// A separator will be hidden if it would be the first visible entry in the list.
    /// A separator will be hidden if it would be the last visible entry in the list.
    /// A separator will be hidden if it would appear right after another separator.
    /// All other separatos will be shown.
    /// </summary>
    /// <param name="items">A collection of ToolStripItems</param>
    /// <param name="includeSubmenus">If true, also cleanup separators in submenus</param>
    public static void CleanUpSeparators(this ToolStripItemCollection items, bool includeSubmenus = true)
    {
        // Will be true when we have last seen a visible item 
        // which is not a separator 
        bool canInsertSeparator = false;

        List<ToolStripSeparator> keepers = new List<ToolStripSeparator>();
        List<ToolStripSeparator> gonners = new List<ToolStripSeparator>();

        ToolStripSeparator lastSeparator = null;

        // Decide which separators should stay and which should go
        for (int i = 0; i < items.Count; i++)
        {
            ToolStripItem item = items[i];

            if (item is ToolStripSeparator)
            {
                if (canInsertSeparator)
                {
                    keepers.Add(item as ToolStripSeparator);
                    lastSeparator = item as ToolStripSeparator;
                    canInsertSeparator = false;
                }
                else
                {
                    gonners.Add(item as ToolStripSeparator);
                }
            }
            else
            {
                // After seeing at least one visible item, we can add a new separator again
                if (item.Available)
                {
                    canInsertSeparator = true;
                }
            }

            // Recursion
            if (includeSubmenus && item is ToolStripDropDownItem)
            {
                (item as ToolStripDropDownItem).DropDownItems.CleanUpSeparators(true);
            }
        }

        if (!canInsertSeparator && lastSeparator != null)
        {
            // The last separator has no following visible other entries, 
            // so we don't want it
            gonners.Add(lastSeparator);
        }

        // Show and hide the separators
        // First show, then hide, because it is possible
        // a separator at the end of the menu is in both lists
        // and it should be hidden
        foreach (var separator in keepers)
        {
            separator.Visible = true;
        }
        foreach (var separator in gonners)
        {
            separator.Visible = false;
        }
    }
}

Это будет использоваться так:

private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
{
    toolStripMenuItemC.Visible = SomeCondition;

    contextMenuStrip1.Items.CleanUpSeparators();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...