Есть ли способ сделать ToolStripMenuItem общим для меню и панелей инструментов?

Я переношу старый проект VB6 на С#, используя Winforms. В оригинале используется пакет ActiveBar от DataDynamic для одновременного управления изменениями нескольких элементов на панелях инструментов, в меню и на ярлыках. Все, что нужно сделать в старом коде, чтобы изменить текст элемента, совместно используемого несколькими меню, панелью инструментов и контекстным меню, — это изменить свойство «Caption» объекта «инструмент».

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

В настоящее время я несколько раз начинал с различных идей, начиная с реализации метода расширения Clone для объектов ToolStripMenuItem и заканчивая тем, чтобы моя форма отслеживала каждый общий объект. Это не удалось, когда я понял, что обновление локальной копии не приведет к обновлению других (мне пришлось бы добавлять сложные события обновления, что требует больше работы, чем простое включение и выключение каждого элемента вручную). Я подумал о том, чтобы создать какой-то способ обновления всех элементов на основе его тега. Это тоже казалось довольно невозможным.

Какие методы вы использовали в подобных ситуациях?


person Chris Pfohl    schedule 30.11.2010    source источник


Ответы (2)


Что ж, на самом деле это одно из раздражающих ограничений .Net GUI-Building Libraries.

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

private void myContextMenuStrip_Opening(object sender, CancelEventArgs e)
{
    myContextMenuStrip.Items.Insert(3, myToolStripMenuItem);
}  

Затем, используя флаги и логику кода, вы сможете узнать, при открытии Menu/ToolBar/ContextMenu, какие элементы он должен отображать.

person Mehdi LAMRANI    schedule 01.12.2010
comment
Меню никогда не отображаются одновременно, что не совсем верно, учитывая, что у нас обоих есть Toolbar категории с Menu и ContextMenu. - person Chris Pfohl; 01.12.2010

В итоге я реализовал SharedMenuItem, в обязанности которого входило регистрировать и обновлять элементы пользовательского интерфейса, которые требовали изменений. Контекстное меню оказалось достаточно другим, чтобы обеспечить собственный обработчик.

Вместо обновления всех элементов меню я обновил SharedMenuItem, который затем позаботился о других изменениях.

[EDIT] Код (добавление других свойств является тривиальным/даже автоматически генерируемым):

public class SharedMenuItem
{
    bool enabled = false;
    public bool Enabled
    {
        get { return enabled; }
        set
        {
            enabled = value;
            foreach (var member in members)
            {
                member.Enabled = value;
            }
        }
    }

    bool visible;
    public bool Visible
    {
        get { return visible; }
        set
        {
            visible = value;
            foreach (var member in members)
            {
                member.Visible = visible;
            }
        }
    }

    string text;
    public string Text
    {
        get { return text; }
        set
        {
            text = value;
            foreach (var member in members)
            {
                member.Text = text;
            }
        }
    }

    string toolTipText = "";
    public string ToolTipText
    {
        get { return toolTipText; }
        set
        {
            toolTipText = value;
            foreach (var member in members)
            {
                member.ToolTipText = toolTipText;
            }
        }
    }

    private List<ToolStripItem> members = new List<ToolStripItem>();

    public void Remove(ToolStripItem member)
    {
        members.Remove(member);
    }

    public void Add(ToolStripItem member)
    {
        members.Add(member);
    }

    public SharedMenuItem(string text)
    {
        this.text = text;
    }
}
person Chris Pfohl    schedule 03.12.2010
comment
Однако с точки зрения дизайна и с технической точки зрения элементы в разных меню, тем более отображаемые одновременно, ЯВЛЯЮТСЯ действительно разными элементами в вашем случае, хотя и указывают на ОДИНАКОВОЕ действие в финале. - person Mehdi LAMRANI; 04.12.2010
comment
Да, это разные элементы, но они должны постоянно иметь общий набор свойств (идеальная возможность шаблона Observer, которая вроде описана выше). - person Chris Pfohl; 06.12.2010