Click here to Skip to main content
15,881,172 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hi,

I hope somebody can give me a hint why my tooltip shows only when the form is opened for the first time.
The scenario is as follows:
1. run the application
2. check if tooltip is showed, close to form FormWithControl
3. press the button buttonOpen to call formMiddle.ShowConfigUI(), now the tooltip doesn't show any more.

The starting form is Form4, which opens formMiddle, which holds UserControl1 and puts it into FormWithControl. The problem that here occures is taht, that I have one UserControl with a tooltip and the UserControl is moved from one Form into another. Then the tooltip doesn't show any more.

I have folowing things programmed:
1. UserControl - a simple user control with a button and a tooltip set on it
this.toolTip1.SetToolTip(this.button1, "Test button");

2. A container form named "FormWithControl", which displays my user control
C#
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. Control form which can cause to open the form "FormWithControl"
C#
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. A class named MiddleClass with following code
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();
    }
}
Posted
Updated 27-Oct-20 14:33pm
v2

... edit October 20, 2013 ...

Summary:

1. In WinForms, in a UserControl: the ToolTip Component, which is an Extender Provider ... unlike other Components, and Controls ... will not function if you change the Parent of the UserControl to another Form (it will, however, function if you change the Parent of the UserControl to another ContainerControl on the same Form). By "not function," I mean: the ToolTips set at design-time on the UserControl's internal Controls will no longer appear at run-time.

2. The reasons why the ToolTip Component appears to become disabled if its hosting UserControl's Parent is changed to another Form are not clear. Quite possibly, the dependency the ToolTip Component has on its internal pointers to Site and Container are affected.

How to "migrate" a ToolTip in a UserControl if the UserControl's Parent is changed to another Form:

0. for educational purposes:

a. assume we have a WinForm App, with a main Form, 'MainForm, with two Panels on it, 'panel1, 'panel2

b. the App has a UserControl, 'userControl1, which has one Button, and two TextBoxes on it, and has a ToolTip component added to it: button1, textBox1, textBox2, toolTip1.

c. one instance of the UserControl1, 'userControl1, has been drag-dropped into the main Form's 'panel1.

d. the App creates another Form, 'Form1

1. define a public method in the UserControl like this:
C#
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;
    }
}
Since the ToolTips for the Controls in the UserControl are not created at design-time: call the 'ChangeParent method in the UserControl's 'Load EventHandler to initialize them:
C#
private void UserControl1_Load(object sender, EventArgs e)
{
    // assume userControl1's inital Parent is 'panel1
    ChangeParent(Parent);
}
Discussion:

1. since 'ChangeParent is a Public method, it can be called from anywhere that has a reference to an instance of the UserControl 'userControl1. So, if you moved the UserControl to another Form, and wanted to then move it back to its original Parent Form, the second Form would have to have a pointer to the original Form, or the ContainerControl on the original Form where they wished to re-site the UserControl (in this example, that would be 'panel1 in the instance of the MainForm).

2. You can see that what's done here is very much a "hack:" the ToolTips are getting cleared and restored every time the Parent of the UserControl is changed.

Conclusion: Use at your own risk, this kind of hack could well be affected in the future by some change by MS. And, as I stress in the original response to this thread (below), it's my opinion that "migrating" Controls from one ControlContainer, or Form, to another is not good programming practice ... in the long run.

... end edit October 2013 ...

While you have discovered you can remove a Control from a Form, and then add it to the ControlCollection of another Form, make it visible, and use it, there is a structural problem possible with using certain Components when you "migrate" Controls this way, and a ToolTip, even though it doesn't appear in the ToolBox for Visual Studio as a Component, is a Component.

But, before talking about the special nature of a ToolTip, I'd like to say that I think moving Controls from one container, Form, UserControl, to another, or from one TabPage to another TabPage, etc., is a very bad idea, and, inherently, is going to lead to problems later on.

If you want to add a new UserControl to Form3, at run-time, with its ToolTip on a Button, exactly the way you configured the UserControl at design-time: just create a new instance of the UserControl and add it to the Form.
Form3 f3 = new Form3();

UserControl1 newUC1 = new UserControl1();

f3.Controls.Add(newUC1);

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

f3.Show();
If you really need to modify, at run-time, various properties or behaviors of the UserControl, then create Public Properties in the UserControl that expose the objects, or fields you need to manipulate:
// 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; }
Then you can do something in your code like:
newUC.UCToolTip.SetToolTip(newUC.UCButton, "Papa's got a brand new bag.");
And now, here's a lot of esoteric detail about Components, and the ToolTip:

Components have a dependency on the special private variable System.ComponentModel you see in every Designer.cs file: private System.ComponentModel.IContainer components = null; When a UserControl, or Form, has Components placed on it, only then is that variable initialized: this.components = new System.ComponentModel.Container();

Some Components in a UserControl, like the Timer, will "survive" migration from one host Control to another with no problem.

But, the ToolTip is a special kind of Component that, potentially, <i>extends</i> capability to every Control on a Form, and the Form, itself. "Under the hood," a ToolTip has its own collection, a ComponentCollection, maintained in its Container.Components field. And, a ToolTip is "sited" in its Container in rather a special way, the "site" itself being an instance of the ISite interface. When a ToolTip is intialized in a Designer.cs Class, you'll note it's done with the form of its constructor that passes its host Control into an IContainer variable.

When you remove a UserControl with a ToolTip from some Form, or UserControl's, ControlCollection, it appears the ToolTip "site" information is "lost." While you might think you could restore that information, and I've tried to do that as an experiment: well, all I can say is that I can't achieve that through a variety of exotic means I've tried. The 'Container property of a ToolTip is read-only, but you can set the 'Site property.
 
Share this answer
 
v3
Comments
Martin3885 19-Oct-13 5:05am    
Thank you very much for your detailed reply Bill. If I understand you right this part of code

public UserControl1()
{
InitializeComponent();
UCToolTip = toolTip1;
UCButton = button1;
}

public ToolTip UC1ToolTip { get; set; }
public Button UC1Button { get; set; }

should solve the problem? I've tried to program it and there is no difference -
the tooltip still doesn't appear.
BillWoodruff 19-Oct-13 7:42am    
I wish it would work, Martin, but the whole point of my reply was that I believe that you simply cannot get a ToolTip to "migrate" if you move a Control from one ControlContainer, or Form, to another. The code I showed was for setting the ToolTip property in a new UserControl instance, not the same instance.

If you really must simulate "migration" with ToolTip, I think you'll have to:

1. in your UserControl create Public Properties for every field the user may alter at run-time

2. create a new instance of the UserControl: copy the values of the properties you need to copy to the new instance from the instance you are going to remove. Then insert the new instance of the UserControl in its new location. Then delete the UserControl you are replacing, and finally, reset the ToolTip content in the new instance.

All of that is quite awkward business, imho, and it would be better, I think, to design in a way where you never needed to "migrate" controls.

good luck, Bill
Martin3885 19-Oct-13 12:40pm    
Oh, now I get it, thanks. Yes, I think, I will have to look at the code and redesign it, if it won't take too much time... Unfortunatelly I don't have it much. The other way to get the tooltip working, would be to call tooltip.Show when the mouse enters the buttton. However you're right that, it would be clean to create the control always when I need to display it, and not doing mess with migrating the control from one Form to another one :).
But if I do it the way, that I recreate the control, I thing I will not need the public tooltip property. If the control is recreated, and the tooltip is already set for buttons in the contol, it will be also working without setting it through the public property. But yes, the other objects which get changed within the control will have to be stored somewhere, before the control is destroyed. Once again thanks for the explanation.
BillWoodruff 19-Oct-13 21:50pm    
Hi Martin, I found a way to achieve what you want, and I'll add it to my "solution" above. It's butt-ugly though :)
Martin3885 20-Oct-13 8:25am    
Hi Bill, it works!! You're great, thanks a lot! :) For my solution, I think, just tooltip.RemoveAll() and toolti.SetTooltip() should be enough.
I had a similar problem and adding a focus right before setting the tooltip fixed my issue:

button1.focus;

toolTip1.SetToolTip(button1, "button1 in panel1");
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900