Moving user controls in a panel doesn't always work

pmacario

Newcomer
Joined
May 4, 2006
Messages
6
Location
Illinois, USA
Hello and thank you in advance to anyone that reads this who may be able to shed some light on the problem.

Now onto the problem:

I have a panel (let's call it panelA) on my Windows form, and I am programmatically adding my own user controls (let's call the user control class myUC) at run-time to panelA's Controls collection. I am doing this in the event handler for a button's Click event. Let's call the button btnAdd. So each time btnAdd is clicked, I do the following in its event handler:

1) add a new myUC() to panelA's Controls collection
2) call a helper method to set the Locations of all the myUC's on panelA (the only controls on panelA are myUC's)

The helper method takes in a single argument of type System.Windows.Forms.Panel which is the panel whose controls are to be re-ordered/re-drawn on the panel.

The Problem:
Sometimes when the myUC's are redrawn on the panel, (although their order and spacing is preserved) there is space from the top of the panel to the top of the first myUC. The myUC's when re-drawn are supposed be start at the top of the panel (0,0). However, sometimes when they re-draw, they appear halfway down the panel. Now I've tried to create new Points and se their location that way. I've also tried to maintain an "anchor" user control on the panel and set the "anchor" user control's Visible property to false. Then, using the "anchor" as a reference point, I tried to set the locations of the dynamically-added myUC's relative to the "anchor," but the problem still exists. Also, I've checked the locations of the controls when they re-draw halfway down the panel, and they actually *think* they're starting at location (0,0)! I really don't know what I'm doing wrong. Any help would be greatly appreciated. Also, if you need to see code, let me know, as I can either post or email a sample Windows Forms application.

Again, thanks in advance.
 
Helper method enclosed

Here is the helper method I use when I re-draw the controls. The user controls are the only controls on the panel.
C#:
/// <summary>
/// Helper method to re-draw the user controls within the panel
/// that contains them.
/// </summary>
/// <param name="currentPanel">Of type System.Windows.Forms.Panel
/// and is Panel that contains the controls to be re-drawn.</param>
private void RedrawRaces(Panel currentPanel)
{
    // for all the controls to be re-drawn
    for (int i = 1; i < currentPanel.Controls.Count; i++)
    {
        switch (i)
        {
            case 1:
                // for the first user control, we set the backcolor to green,
                // we set the location to the anchor user control's location,
                // and for debugging purposes, we set the label text to show
                // the location of the control. (or at least where the control
                // would like to think that it's located.)
                currentPanel.Controls[1].BackColor = Color.LawnGreen;
                
                // the anchor user control is located at (0,2)
                currentPanel.Controls[1].Location = 
                    currentPanel.Controls[0].Location;

                // the line below is for using the label text to display the 
                // supposed location of the user control on the panel
                ((ucRace)currentPanel.Controls[1]).LblRaceText =
                    currentPanel.Controls[1].Location.ToString();
                
                break;

            case 2:
                // for the second user control, we set the backcolor to yellow,
                // we set the location relative to the previous user control's 
                // location, and for debugging purposes, we set the label text 
                // to show the location of the control. 
                currentPanel.Controls[2].BackColor = Color.Yellow;
                currentPanel.Controls[2].Location =
                    new Point(currentPanel.Controls[1].Location.X,
                    currentPanel.Controls[1].Location.Y + 3 + 155);

                // the line below is for using the label text to display the 
                // supposed location of the user control on the panel
                ((ucRace)currentPanel.Controls[2]).LblRaceText = 
                    currentPanel.Controls[2].Location.ToString();
                
                break;
        
            default:
                // for all other user controls, we set the backcolor to red,
                // we set the location relative to the previous user control's 
                // location, and for debugging purposes, we set the label text 
                // to show the location of the control.
                currentPanel.Controls[i].BackColor = Color.Red;
                currentPanel.Controls[i].Location =
                    new Point(currentPanel.Controls[i - 1].Location.X,
                    currentPanel.Controls[i - 1].Location.Y + 3 + 155);

                // the line below is for using the label text to display the 
                // supposed location of the user control on the panel
                ((ucRace)currentPanel.Controls[i]).LblRaceText = 
                    currentPanel.Controls[i].Location.ToString();
                
                break;
        }
    }
}
 
Last edited by a moderator:
I've had a quick look at your code and theres one thing that confuses me, in the switch statement you seem to refer to case 1 as being the first control, wheras technically the first control in a control collection is in position 0. For example you say in your comments change the first control to green, then infact change the second one. But then you go on to change the second controls position to equal the first, I guess I'm just confused about what exactly is going on.
 
I thought I'd mentioned it. I have an "anchor" user control which is Controls[0]. It is placed on the form at location (0,2), and its Visible property is set to false. I am setting the locations of all the visible user controls relative to this "anchor" user control. This is all done in an attempt to make the user controls draw properly on the panel.

Before I had this "anchor" user control, I did have the helper method setting the location of the first control Controls[0] at (0,2) and all the rest of the controls' locations were set relative to the first. However, with or without the "anchor", I have the same re-draw problem.
 
Ok, sorry, my bad, I went back to your first post and I now see what you were doing. When you say it *thinks* the controls are in the right place, I assume you mean that whenever you look at the location property it reports the right position, regardless of the fact it appears to be in the wrong place? If this is the case I would ask if you have overriden any of the paint events for the usercontrol, as it sounds like a drawing issue rather than a positioning one.
 
Cags said:
Ok, sorry, my bad, I went back to your first post and I now see what you were doing. When you say it *thinks* the controls are in the right place, I assume you mean that whenever you look at the location property it reports the right position, regardless of the fact it appears to be in the wrong place? If this is the case I would ask if you have overriden any of the paint events for the usercontrol, as it sounds like a drawing issue rather than a positioning one.

Unless you can do it implicitly (and unknowingly), I haven't overridden any paint events for the user control.

Also, as you can see from the code snippet, the label text on the user control is being made to display the user control's location on the panel. The user controls on the panel (as a group) are sequentially spaced fine, but that first control will display its location as (0,2) even though it physically appears halfway down the panel at a location which cannot possibly be (0,2) but must be more like... (0,402). The y coordinate is way off. The x coordinate, however, is right on. So horizontally, they're in the right place, but vertically, they're way off.
 
Cags said:
If you post a sample project I can have a look for you (or send it to me), but I can't see anything that is inherantly wrong with the code posted.

I think you need to enable emails from other forum members or something before I can send you an email. I tried to do this just now, but you don't seem to have this setting enabled.
 
Thanks to everyone for all the efforts in helping me, but I've figured out what was wrong. Because I had the panel's AutoScroll property set to "true", the panel was often still SCROLLED when I called my helper re-draw/re-position method. Now, what I didn't know when I wrote the re-draw/re-position method was that when you do set locations of controls or anything on a panel, it considers the locations that you set relative to the visible part of the panel. So, it was using as its origin point (0,0) the top-left corner of the panel that was visible at the time. Solution? One-liner.

panelA.AutoScrollPosition = new Point(0,0);

This line sets the position of the auto-scrollbar to the top of the panel. Thus, all is well again in the world.
 
Back
Top