С# - Дублировать элементы ContextMenuStrip в другой

У меня есть два ContextMenuStrip в приложении Windows Form, один из них имеет 3 элемента, а другой - ни одного.

Предположим, это:

ContextMenuStrip c1 = new ContextMenuStrip();
ContextMenuStrip c2;

c1 имеет 3 ToolStripMenuItems, c2 - это место назначения ContextMenuStrip, где элементы c1 должны быть продублированы.

Я пытался написать это:

c2 = new ContextMenuStrip(c1.Container);

но это дает мне ArgumentNullException, потому что c1.Container равно null.

Я не могу понять, как это решить, вы можете мне помочь?

Пс. Я бы new ToolStripMenuItem (с), без ссылок

а также

Решения с while или foreach петлями - не лучший способ сделать это.

Спасибо :)


person ewhoambra    schedule 17.06.2016    source источник
comment
Где-то у вас есть код, который создает объект ContextMenuStrip. Позвони еще раз.   -  person Hans Passant    schedule 17.06.2016
comment
Можете ли вы привести пример?   -  person ewhoambra    schedule 17.06.2016


Ответы (3)


Затем создайте функцию, которая создает ContextMenuStrip и вызывает ее каждый раз, когда требуется новое меню.

Func<ContextMenuStrip> newContextMenuStrip = () => { 
    var c = new ContextMenuStrip();
    c.Items.Add("item 1");
    c.Items.Add("item 2");
    c.Items.Add("item 3");
    return c;
};

var c1 = newContextMenuStrip();
var c2 = newContextMenuStrip();
person Slai    schedule 17.06.2016
comment
Хм... попробую, дам знать - person ewhoambra; 17.06.2016
comment
Это невероятное решение, и оно прекрасно работает. Большое спасибо :) - person ewhoambra; 17.06.2016

Поздно на вечеринку, но у меня была такая же проблема в прошлом, и я нашел достаточно простое решение.

Скажем, ваш toolStripMenuItem объявлен как «TSMI_open» в контекстном меню, вы можете эффективно переключать его между контекстными меню по мере их открытия. Что-то вроде этого:

void Context1_Opening(object sender, CancelEventArgs e)
{
     Context1.Items.Insert(0, TSMI_open);
}

void Context2_Opening(object sender, CancelEventArgs e)
{
     Context2.Items.Insert(0, TSMI_open);
}

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

person Irvingz    schedule 03.12.2017

Вам нужно создать новый ContextMenuStrip и добавить Items (а не Container из c1 в новое меню:

c2 = new ContextMenuStrip();
c2.Items.AddRange(c1.Items);

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

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

Простым примером может быть:

c2.Items.AddRange(c1.Items.OfType<ToolStripItem>()
                           .Select(item => new ToolStripMenuItem(item.Text))
                           .OfType<ToolStripItem>().ToArray());

Второй OfType необходим, чтобы избежать ковариантного преобразования массива из ToolStripMenuItem[] в ToolStripItem[], которое ожидается AddRange().


И примечание: Container — это компонент, который содержит меню (поэтому null, когда меню не отображается), а не то, в чем меню хранит свои элементы.

person René Vogt    schedule 17.06.2016
comment
Да, вы правы, это дает мне те же экземпляры, но не новый клонированный экземпляр... но спасибо :) - person ewhoambra; 17.06.2016
comment
@EdoardoChiabra Клонировать элементы немного сложнее, и я не думаю, что вы можете сделать это в одну строку. Во-первых, вам нужно позаботиться о конкретном типе элемента, во-вторых, вам нужно знать, какие свойства вы хотите клонировать, и это особенно сложно для обработчиков событий Click. - person René Vogt; 17.06.2016
comment
Я знаю, что однострочное решение утопично, что вы предлагаете по этому поводу? Петля? - person ewhoambra; 17.06.2016
comment
@EdoardoChiabra, это слишком широко, чтобы ответить (по крайней мере, в комментариях). Это во многом зависит от свойств, которые вы хотите клонировать, и от того, откуда берется эта информация (особенно от обработчиков событий). Я слишком мало знаю о том, чего вы действительно пытаетесь достичь, например. почему вы вообще хотите их клонировать. - person René Vogt; 17.06.2016
comment
@EdoardoChiabra добавил небольшой пример того, что может быть возможно, но он клонирует только свойство Text и генерирует только ToolStripMenuItems, никаких других производных ToolStripItem. - person René Vogt; 17.06.2016
comment
Потому что во время выполнения программа создает несколько кнопок. Каждой кнопке нужен ContextMenuStrip, дублированный из модели c1. Затем код задает свойство Enabled для каждого элемента ToolStripMenuItem в ContextMenuStrip, связанного с кнопкой. У каждого ToolStripMenuItem есть Click EventHandler, но на самом деле я не возражаю против этого прямо сейчас! - person ewhoambra; 17.06.2016