Вы должны войти, чтобы создавать сообщения и темы.

Сложности с созданием динамического контрола [Решено]

Доброго времени суток

У меня на форме используется некий аналог выпадающего списка с чекБоксом. И при запуске формы этот контрол скрывается. Открывается при клике на текстБокс.

Но вот в визуальном конструкторе этот контрол виден всегда, и перекрывает другие контролы, ведь он поверх ниже отображается. Я подумал что может стоит создавать этот контрол динамически? При запуске формы.

Вот что у меня в текстовом дизайнере

private void InitializeComponent()
        {
            this.langCheckedListBox1 = new System.Windows.Forms.CheckedListBox();
            // 
            // langCheckedListBox1
            // 
            this.langCheckedListBox1.Font = new System.Drawing.Font("Verdana", 9F);
            this.langCheckedListBox1.FormattingEnabled = true;
            this.langCheckedListBox1.Items.AddRange(new object[] {
            "Японский",
            "Китайский",
            "Корейский",
            "Английский",
            "Русский"});
            this.langCheckedListBox1.Location = new System.Drawing.Point(110, 255);
            this.langCheckedListBox1.MultiColumn = true;
            this.langCheckedListBox1.Name = "langCheckedListBox1";
            this.langCheckedListBox1.Size = new System.Drawing.Size(365, 55);
            this.langCheckedListBox1.TabIndex = 48;
            this.langCheckedListBox1.TabStop = false;
            this.langCheckedListBox1.Visible = false;
            this.langCheckedListBox1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.langCheckedListBox1_Changed);
            this.langCheckedListBox1.SelectedValueChanged += new System.EventHandler(this.langCheckedListBox1_Changed);
            this.langCheckedListBox1.DoubleClick += new System.EventHandler(this.langCheckedListBox1_Changed);
            this.langCheckedListBox1.Enter += new System.EventHandler(this.langTextBox1_EnterLeave);
            this.langCheckedListBox1.Leave += new System.EventHandler(this.langTextBox1_EnterLeave);
            this.langCheckedListBox1.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.langCheckedListBox1_Changed);
            this.langCheckedListBox1.MouseEnter += new System.EventHandler(this.langTextBox1_EnterLeave);
            this.langCheckedListBox1.MouseLeave += new System.EventHandler(this.langTextBox1_EnterLeave);
            // 
            // Form1
            // 

            this.Controls.Add(this.langCheckedListBox1);
        }
        #endregion
        private System.Windows.Forms.CheckedListBox langCheckedListBox1;

Я пытаюсь продублировать его в Form1_Load

TextBox langCheckedListBox1 = new TextBox();
langCheckedListBox1.Font = new System.Drawing.Font("Verdana", 9F);
langCheckedListBox1.FormattingEnabled = true;
langCheckedListBox1.Items.AddRange(new object[] {
"Японский",
"Китайский",
"Корейский",
"Английский",
"Русский"});
langCheckedListBox1.Location = new System.Drawing.Point(110, 255);
langCheckedListBox1.MultiColumn = true;
langCheckedListBox1.Name = "langCheckedListBox1";
langCheckedListBox1.Size = new System.Drawing.Size(365, 55);
langCheckedListBox1.TabIndex = 48;
langCheckedListBox1.TabStop = false;
langCheckedListBox1.Visible = false;
langCheckedListBox1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.langCheckedListBox1_Changed);
langCheckedListBox1.SelectedValueChanged += new System.EventHandler(this.langCheckedListBox1_Changed);
langCheckedListBox1.DoubleClick += new System.EventHandler(this.langCheckedListBox1_Changed);
langCheckedListBox1.Enter += new System.EventHandler(this.langTextBox1_EnterLeave);
langCheckedListBox1.Leave += new System.EventHandler(this.langTextBox1_EnterLeave);
langCheckedListBox1.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.langCheckedListBox1_Changed);
langCheckedListBox1.MouseEnter += new System.EventHandler(this.langTextBox1_EnterLeave);
langCheckedListBox1.MouseLeave += new System.EventHandler(this.langTextBox1_EnterLeave);
Controls.Add(langCheckedListBox1);

Но получаю кучу ошибок


Если после этого я удалю оригинальный контрол из дизайнера, то получу еще ошибки.

Есть какой то способ это все исправить? Или невозможно такой сложный контрол создать динамически?


Комментарий модератора:
Ознакомьтесь ➞ Как делать крутые скриншоты

Привет! Проблема в том, что то, что написано в дизайнере не стоит копировать 1 в 1. Там он объявляется глобально, что его можно получить из любой точки Твоей программы (в пределах класса Form)

Пример создания на лету

CheckedListBox langChecker = new CheckedListBox {
    Location = new Point(110, 255),
    MultiColumn = true,
    Size = new Size(365, 55),
    Visible = false, // скрываем пока не ненужен
    // ...что-то еще
};
// теперь привязываем события
langChecker.MouseClick += (s, a) => { 
    // что происхожит на клик
};
// ...другие события

foreach (string lang in new string[] {
    "Японский",
    "Китайский",
    "Корейский",
    "Английский",
    "Русский"
})
    langChecker.Items.Add(lang); // при создании определить список незя(

this.Controls.Add(langChecker); // создаем котнтрол на форме

Только надо учитывать, что Ты создаешь переменную, поэтому она будет доступна только в пределах Form_Load
Также рекомендую к просмотру ролик Хачатура про лямбду

Лайкнул Валера
Валера
Цитата: yuri от 13.11.2023, 18:37

Также рекомендую к просмотру ролик Хачатура про лямбду

Ну так я именно с этого видео узнал как создавать события на лету

Вот я пытаюсь сделать как вы сказали

public void Form1_Load(object sender, EventArgs e)
        {
            CheckedListBox langCheckedListBox1 = new CheckedListBox
            {
                Font = new Font("Verdana", 9F),
                FormattingEnabled = true,
                Location = new Point(110, 255),
                MultiColumn = true,
                Name = "langCheckedListBox1",
                Size = new Size(365, 55),
                TabIndex = 48,
                TabStop = false,
                Visible = false
            };

            foreach (string lang in new string[]
            {
                "Японский",
                "Китайский",
                "Корейский",
                "Английский",
                "Русский"
            });
            //langCheckedListBox1.Items.Add(lang);

            this.Controls.Add(langCheckedListBox1); // создаем котнтрол на форме

Я закомментировал то что выдает ошибки

СкопированоlangCheckedListBox1.Items.Add(langs); Ошибка CS0103 Имя "lang" не существует в текущем контексте.

Дальше проблемы с созданиями событий. Этот код
Скопированоthis.langCheckedListBox1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.langCheckedListBox1_Changed); - говорит что событие  "MouseClick" обрабатывает код другого события - СкопированоlangCheckedListBox1_Changed. Верно? И к нему и некоторые другие события так же ссылаются. И вот что делать с событием "langCheckedListBox1_Changed"? Оно вот так выглядит

public void langCheckedListBox1_Changed(object sender, EventArgs e)
{
    List<string> L = new List<string>();
    for (int i = 0; i < langCheckedListBox1.CheckedItems.Count; i++)
    {
        L.Add(langCheckedListBox1.CheckedItems[i].ToString());
    }

    string str = string.Join(", ", L);  /*Конвертация массива в строку*/
    langTextBox1.Text = "";
    langTextBox1.Text = str;                         /*Вывод массива в строку*/

    TextBox_ChangeText(langTextBox1, defaultLangTextBox1);
    TextBox_ChangeTextColor(langTextBox1, defaultLangTextBox1);
}

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

private void langTextBox1_MouseClick(object sender, MouseEventArgs e)
{
    if (langCheckedListBox1.Visible)
        langCheckedListBox1.Visible = false;
    else
        langCheckedListBox1.Visible = true;
}

И с этим опять проблемы. Я не смогу достучаться в Скопированоpublic void Form1_Load(object sender, EventArgs e). Что делать? Это вообще возможно?

Так ладно, я перенес контрол с Form1_Load в class Form1 : Form. Часть проблемы решил. Теперь я могу свой динамический контрол показывать и скрывать.

Еще одну проблему решил

string[] langs =
{
    "Японский",
    "Китайский",
    "Корейский",
    "Английский",
    "Русский"
};
          
foreach (string lang in langs)
{
    langCheckedListBox1.Items.Add(lang);
};

 

О! Все, я допетрав как все сделать

langCheckedListBox1.MouseClick += (s, a) => {
    langCheckedListBox1_Changed(s, a);
};

langCheckedListBox1.SelectedValueChanged += (s, a) => {
    langCheckedListBox1_Changed(s, a);
};

langCheckedListBox1.DoubleClick += (s, a) => {
    langCheckedListBox1_Changed(s, a);
};

langCheckedListBox1.Enter += (s, a) => {
    langTextBox1_EnterLeave(s, a);
};

langCheckedListBox1.Leave += (s, a) => {
    langTextBox1_EnterLeave(s, a);
};

langCheckedListBox1.MouseDoubleClick += (s, a) => {
    langCheckedListBox1_Changed(s, a);
};

langCheckedListBox1.MouseEnter += (s, a) => {
    langTextBox1_EnterLeave(s, a);
};

langCheckedListBox1.MouseLeave += (s, a) => {
    langTextBox1_EnterLeave(s, a);
};

Все получилось, спасибо, тему можно закрывать...