Martin3885 Ответов: 2

Всплывающая подсказка не появляется снова, когда элемент управления перемещается в другое окно


Привет,

Я надеюсь, что кто-то может дать мне подсказку, почему моя подсказка отображается только тогда, когда форма открыта в первый раз.
Сценарий выглядит следующим образом:
1. Запустите приложение
2. Проверьте, отображается ли всплывающая подсказка, рядом с формой FormWithControl
3. Нажмите кнопку buttonOpen, чтобы вызвать formMiddle.ShowConfigUI(), теперь всплывающая подсказка больше не отображается.

Стартовая форма-Form4, которая открывает formMiddle, который содержит UserControl1 и помещает его в FormWithControl. Проблема, которая здесь возникает, заключается в том, что у меня есть один пользовательский элемент управления с подсказкой, и пользовательский элемент управления перемещается из одной формы в другую. Затем всплывающая подсказка больше не отображается.

У меня запрограммированы следующие вещи:
1. UserControl - простой пользовательский элемент управления с установленной на нем кнопкой и всплывающей подсказкой
это.toolTip1.SetToolTip(это.кнопки "button1", тест"");

2. Контейнер форма имени "FormWithControl", который отображает мой пользовательский элемент управления
public partial class FormWithControl : Form
{
    MiddleClass _formMiddle;
    public FormWithControl(MiddleClass formMiddle)
    {
        InitializeComponent();
        _formMiddle = formMiddle;
    }

    public void InitalizeShow(UserControl1 usctr)
    {
        base.Controls.Add(usctr);
    }

    public void Show(bool flag)
    {
        base.Show();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        base.Close();
    }

    private void FormWithControl_FormClosing(object sender, FormClosingEventArgs e)
    {
        _formMiddle.CloseConfigUI();
    }

    public void RemoveControls()
    {
        base.Controls.RemoveAt(1);
    }
}



3. Контроль формы, который может вызвать, чтобы открыть форму "FormWithControl"
public partial class Form4 : Form
    {
        MiddleClass formMiddle;

        public Form4()
        {
            InitializeComponent();
            formMiddle = new MiddleClass();
            formMiddle.InitConfigUI();
        }

        private void buttonOpen_Click(object sender, EventArgs e)
        {
            formMiddle.ShowConfigUI();
        }
    }


4. Класс с именем среднего класса с помощью следующего кода
public class MiddleClass
{
    FormWithControl formWithControl;
    UserControl1 userControl1;

    public MiddleClass()
    {
        userControl1 = new UserControl1();
    }

    public void InitConfigUI()
    {
        formWithControl = new FormWithControl(this);
        formWithControl.InitalizeShow(userControl1);
        formWithControl.Show(true);
    }

    public void ShowConfigUI()
    {
        formWithControl = new FormWithControl(this);
        formWithControl.InitalizeShow(userControl1);
        userControl1.Parent = formWithControl;
        formWithControl.Show(true);
        userControl1.Focus();
    }

    public void CloseConfigUI()
    {
        formWithControl.RemoveControls();
        formWithControl.Hide();
    }
}

2 Ответов

Рейтинг:
2

Member 14828883

У меня была похожая проблема и добавление фокуса прямо перед установкой всплывающей подсказки исправило мою проблему:

button1.focus;

toolTip1.SetToolTip(button1, "button1 in panel1");


Рейтинг:
18

BillWoodruff

.. правка 20 октября 2013 года ...

Резюме:

1. В WinForms, в пользовательских элементов управления: компонент tooltip, который является поставщиком расширитель ... в отличие от других компонентов и элементов управления ... не будет функционировать, если вы измените родительский элемент UserControl на другую форму (однако он будет функционировать, если вы измените родительский элемент UserControl на другой ContainerControl в той же форме). Под "Не функцией" я подразумеваю: всплывающие подсказки, установленные во время разработки на внутренних элементах управления UserControl, больше не будут появляться во время выполнения.

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

Как "перенести" всплывающую подсказку в UserControl, если родительский элемент UserControl изменен на другую форму:

0. в образовательных целях:

а. предположим, что у нас есть приложение WinForm с основной формой, 'MainForm, с двумя панелями на нем, 'panel1, 'panel2

б. приложение имеет UserControl, 'userControl1, который имеет одну кнопку и два текстовых поля на нем, а также имеет компонент всплывающей подсказки, добавленный к нему: button1, textBox1, textBox2, toolTip1.

c. один экземпляр UserControl1, 'userControl1, был перетащен в панель основной формы' panel1.

d. приложение создает другую форму, 'Form1

1. Определите открытый метод в UserControl следующим образом:

public void ChangeParent(Control newParent)
{
    // clear the existing ToolTips
    toolTip1.RemoveAll();

    // remove the UserControl from its current host's ControlCollection
    this.Parent.Controls.Remove(this);

    // add the UserControl to its new host's ControlsCollection
    newParent.Controls.Add(this);

    // reset the ToolTip depending on the new host
    switch (newParent.Name)
    {
        case "panel1":
            toolTip1.SetToolTip(button1, "button1 in panel1");
            toolTip1.SetToolTip(textBox1, "textBox1 in panel1");
            toolTip1.SetToolTip(textBox2, "textBox2 in panel1");
            break;
        case "panel2":
            toolTip1.SetToolTip(button1, "button1 in panel2");
            toolTip1.SetToolTip(textBox1, "textBox1 in panel2");
            toolTip1.SetToolTip(textBox2, "textBox2 in panel2");
            break;
        case "Form1":
            toolTip1.SetToolTip(button1, "button1 in Form1");
            toolTip1.SetToolTip(textBox1, "textBox1 in Form1");
            toolTip1.SetToolTip(textBox2, "textBox2 in Form1");
            break;
    }
}
Поскольку всплывающие подсказки для элементов управления в UserControl не создаются во время разработки: вызовите метод ChangeParent в обработчике событий загрузки UserControl, чтобы инициализировать их:
private void UserControl1_Load(object sender, EventArgs e)
{
    // assume userControl1's inital Parent is 'panel1
    ChangeParent(Parent);
}
Обсуждение:

1. поскольку 'ChangeParent является общедоступным методом, он может быть вызван из любого места, имеющего ссылку на экземпляр UserControl 'userControl1. Таким образом, если вы переместили UserControl в другую форму и хотите затем переместить его обратно в исходную родительскую форму, вторая форма должна иметь указатель на исходную форму или ContainerControl в исходной форме, где они хотели бы повторно разместить UserControl (в данном примере это будет 'panel1 в экземпляре основной формы).

2. Вы можете видеть, что то, что здесь сделано, очень похоже на "взлом": всплывающие подсказки очищаются и восстанавливаются каждый раз, когда изменяется родительский элемент UserControl.

Вывод: используйте на свой страх и риск, этот вид взлома вполне может быть затронут в будущем некоторыми изменениями со стороны MS. И, как я подчеркиваю в первоначальном ответе на эту тему (ниже), я считаю, что "перенос" элементов управления из одного ControlContainer или формы в другую не является хорошей практикой программирования ... в долгосрочной перспективе.

.. конец октября 2013 года ...

В то время как вы открыли себя мочь удалите элемент управления из формы, а затем добавьте его в коллекцию ControlCollection другой формы, сделайте его видимым и используйте его. структурный проблему можно с помощью определенный Компоненты, когда вы "переносите" элементы управления таким образом, и всплывающую подсказку, даже если это не так появиться в наборе инструментов для Visual Studio как компонент, является компонент.

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

Если вы хотите добавить новый UserControl в Form3 во время выполнения, с его подсказкой на кнопке, точно так же, как вы настроили UserControl во время разработки: просто создайте новый экземпляр UserControl и добавьте его в форму.
Form3 f3 = new Form3();

UserControl1 newUC1 = new UserControl1();

f3.Controls.Add(newUC1);

// position it, etc.
newUC1.Location = new Point(50,50);

f3.Show();
Если вам действительно нужно изменить во время выполнения различные свойства или поведение элемента управления UserControl, то создайте в нем общедоступные свойства, которые предоставляют доступ к объектам или полям, которыми вам нужно манипулировать:
// note the UserControl 'Load Event will not be called when you instantiate a UserControl in code !
public UserControl1()
{
    InitializeComponent();
    UCToolTip = toolTip1;
    UCButton = button1;
}

public ToolTip UC1ToolTip { get; set; }
public Button UC1Button { get; set; }
Затем вы можете сделать что-то в своем коде, например:
newUC.UCToolTip.SetToolTip(newUC.UCButton, "Papa's got a brand new bag.");
А теперь вот много эзотерических подробностей о компонентах и подсказке:

Компоненты имеют зависимость от специальной системы частных переменных.ComponentModel вы видите в каждом файле Designer.cs: частная система.ComponentModel.Компоненты # то # = значение null; когда элемент управления UserControl, или форма, есть компоненты, помещенные в ней, только то, что переменная инициализирована: это.компоненты = новая система.ComponentModel.Контейнер();

Некоторые компоненты в UserControl, такие как таймер, "переживут" миграцию с одного хост-элемента управления на другой без каких-либо проблем.

Но подсказка-это особый вид компонента, который потенциально расширяет возможности каждого элемента управления в форме и самой формы. "Под капотом" всплывающая подсказка имеет свою собственную коллекцию, ComponentCollection, поддерживаемую в ее контейнере.Поле компонентов. Кроме того, всплывающая подсказка "размещается" в своем контейнере довольно особым образом, причем сам "сайт" является экземпляром интерфейса ISite. Когда всплывающая подсказка инициализируется в классе Designer.cs, вы заметите, что это делается с помощью формы его конструктора, который передает свой хост-элемент управления в переменную IContainer.

Когда вы удалите элемент управления UserControl с подсказкой от той или иной форме, или элемент управления UserControl, в controlcollection с ним появляется всплывающая подсказка "сайт" информация "теряется." Хотя вы можете подумать, что можете восстановить эту информацию, и я попытался сделать это в качестве эксперимента: ну, все, что я могу сказать, это то, что я не могу достичь этого с помощью различных экзотических средств, которые я пробовал. Свойство "контейнер" всплывающей подсказки доступно только для чтения, но вы можете установить свойство "сайт".


Martin3885

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

общественные файл usercontrol1()
{
метод InitializeComponent();
UCToolTip = toolTip1;
UCButton = button1;
}

public ToolTip UC1ToolTip { get; set; }
публичная кнопка UC1Button { get; set; }

следует ли решить эту проблему? Я пытался запрограммировать его и нет никакой разницы -
подсказка по-прежнему не появляется.

BillWoodruff

Я хотел бы, чтобы это сработало, Мартин, но весь смысл моего ответа состоял в том, что я считаю, что вы просто не можете получить подсказку для "миграции", если вы перемещаете элемент управления из одного ControlContainer или формы в другую. Код, который я показал, предназначался для установки свойства ToolTip в новом экземпляре UserControl, а не в том же экземпляре.

Если вам действительно нужно смоделировать "миграцию" с помощью всплывающей подсказки, я думаю, вам придется это сделать:

1. в вашем UserControl создайте общедоступные свойства для каждого поля, которое пользователь может изменить во время выполнения

2. Создайте новый экземпляр UserControl: скопируйте значения свойств, которые вам нужно скопировать, в новый экземпляр из экземпляра, который вы собираетесь удалить. Затем вставьте новый экземпляр UserControl в его новое местоположение. Затем удалите заменяемый элемент управления UserControl и, наконец, сбросьте содержимое всплывающей подсказки в новом экземпляре.

Все это довольно неудобное дело, ИМХО, и было бы лучше, я думаю, проектировать таким образом, чтобы вам никогда не нужно было "переносить" элементы управления.

удачи тебе, Билл

Martin3885

О, теперь я понимаю, Спасибо. Да, я думаю, мне придется посмотреть код и переработать его, если это не займет слишком много времени... К сожалению, у меня их не так уж много. Другой способ заставить всплывающую подсказку работать-это вызвать всплывающую подсказку.Показать, когда мышь входит в кнопку. Однако вы правы в том, что было бы чисто создавать элемент управления всегда, когда мне нужно его отобразить, а не возиться с переносом элемента управления из одной формы в другую :).
Но если я сделаю это так, что воссоздам элемент управления, то мне не понадобится свойство public tooltip. Если элемент управления воссоздан, а всплывающая подсказка уже настроена для кнопок в contol, он также будет работать без установки его через общедоступное свойство. Но да, другие объекты, которые изменяются внутри элемента управления, должны быть где-то сохранены, прежде чем элемент управления будет уничтожен. Еще раз спасибо за объяснение.

BillWoodruff

Привет, Мартин, я нашел способ достичь того, чего ты хочешь, и добавлю его к своему "решению" выше. Хотя это уродливо для задницы :)

Martin3885

Привет, Билл, это работает!! Ты молодец, большое спасибо! :) Для моего решения, я думаю, просто tooltip.RemoveAll() и toolti.SetTooltip() должно быть достаточно.