Search code examples
c#winformslinklabel

Programmatically added LinkLabel not visible


I am encountering a strange phenomenon: I have a WinForms application with four GroupBoxes, all four initially empty. I use this to track new followers/unfollowers on Twitter, planning on expanding its use once this functions properly.

It does work properly for new followers. For these I have a GroupBox called grpFollow, to which I add LinkLabels with the ScreenNames of my new followers like this:

var folTop = new Point(grpFollow.Left + 5, grpFollow.Top + 5);
lblFollowers.Text = Properties.Settings.Default.FollowersNow.Count.ToString();
lblFriends.Text = Properties.Settings.Default.FriendsNow.Count.ToString();
var ctr = 1;
foreach (var fol in newFollowers)
{
    var kvp = LookupUser(fol);
    if (string.IsNullOrEmpty(kvp.Key)) continue;
    var linklabel = new LinkLabel()
    {
        Text = kvp.Value,
        Width = 200,
        Height = 15,
        Location = folTop,
        Visible = true,
        Name = $"follbl{ctr}"
    };
    ctr++;
    linklabel.Links.Add(0, linklabel.Width-1, $"https://twitter.com/{kvp.Key}");
    linklabel.Click += Linklabel_Click;
    grpFollow.Controls.Add(linklabel);
    folTop.Y += 25;
}

LookupUser is just a function that passes the user id to the Twitter API and returns the name & screen_name of that user. Works fine, no problem. LinkLabels added nicely, no problem there either.

The trouble is with the other group boxes, e.g. the one for new friends:

folTop = new Point(grpFriends.Left + 15, grpFriends.Top + 15);
ctr = 1;
foreach (var fol in newFriends)
{
    var kvp = LookupUser(fol);
    if (string.IsNullOrEmpty(kvp.Key)) continue;
    var llabel = new LinkLabel()
    {
        Text = kvp.Value,
        Width = 200,
        Height = 15,
        Location = folTop,
        Visible = true,
        Name = $"frdlbl{ctr}"
    };
    ctr++;
    llabel.Links.Add(0, llabel.Width - 1, $"https://twitter.com/{kvp.Key}");
    llabel.Click += Linklabel_Click;
    grpFriends.Controls.Add(llabel);
    folTop.Y += 25;
}

As you can see, the logic is identical (because I want to extract this part to a separate method to avoid repetition). The location is set relative to the grpFriends group box, everything else is the same. Yet, the LinkLabel does not show, i.e. the second group box remains (visually) empty!

I have set a breakpoint to check what might go wrong. I single stepped through: the correct screen name is being retrieved, the location is correct, the control is added - but nothing ever shows up.

P.S: This code is in the RunWorkerCompleted method of a background worker, no further code is executed after this point.

Any idea why the Label isn't displayed?

Edit: I'll be damned! I just changed the location of the grpFriends LinkLabel to 10,10: it appears, juuust clipping the lower border of my friends' group.

Now here is where this gets weird for me: grpFriends location values

As you can see, the group has a Y value of 351. Point (10,10) should not even be in the box. So, it seems that the location is the culprit and the original code created the label outside the form.

Replacing grpFriends.Top as Y value with grpFriends.Top - grpFriends.Height got me closer. The LinkLabel is farther down from the top than I'd like but that's not so bad.

Very strange.


Solution

  • Okay, thanks to @raBinn I figured it out. The mistake here was me assuming, the LinkLabels needed a location relative to the Form. However, when adding them to the Controls collection of a GroupBox, they automatically assume a location relative to the GroupBox, not the Form.

    So, my code is now basically the same for all four group boxes and looks like this:

    PopulateGroup(newFollowers, grpFollow);
    PopulateGroup(unFollow, grpLost);
    PopulateGroup(newFriends, grpFriends);
    PopulateGroup(unFriend, grpDitched);
    

    And:

    private void PopulateGroup(List<string> collPeople, GroupBox groupBox)
    {
        var folTop = new Point(12, 25);
        foreach (var fol in collPeople)
        {
            var kvp = LookupUser(fol);
            if (string.IsNullOrEmpty(kvp.Key)) continue;
            var linklabel = new LinkLabel()
            {
                Text = kvp.Value,
                Width = 200,
                Height = 15,
                Location = folTop
            };
            ctr++;
            linklabel.Links.Add(0, linklabel.Width - 1, $"https://twitter.com/{kvp.Key}");
            linklabel.Click += Linklabel_Click;
            groupBox.Controls.Add(linklabel);
            folTop.Y += 25;
        }
    }
    

    So it doesn't really matter whether the group box is on the left or right, top or bottom of the form...