0
votes

I am trying to dynamically create Windows controls and add them to a Panel. For Button and Checkbox this has worked fine; I've run into a problem with a GroupBox, though, with RadioButtons inside it.

The first RadioButton element is created and added to the GroupBox in the expected location, but susbequent ones, although ostensibly created (stepping through the code makes that appear to be the case), they are not visible.

I would think that if subsequent RadioButtons were being plopped atop the previous ones, the last one would be the one seen. This is what it looks like:

enter image description here

Each ~-delimited val should be the text value of a radioButton, yet only one displays. Do I need to explicitly provide the Location vals for the subsequent RadioButtons, or why is this failing?

Here is the code:

private GroupBox getGroupBox(string currentSettings, int curLeftVal)
{
    // "apple~orange~peach~True (must look for "enclose group in a black box" as the last val (ignore for the quick-and-dirty mockup, though))
    List<string> grpbxVals = new List<string>(currentSettings.Split('~'));
    GroupBox gb = new GroupBox();
    gb.Height = 60;
    gb.Location = new Point(curLeftVal, PANEL_TOP_LOC);
    RadioButton radbtn = null;
    // "-1" because we're ignoring the final bool ("enclose in black box")
    for (int i = 0; i < grpbxVals.Count-1; i++)
    {
        radbtn = new RadioButton();
        radbtn.Text = grpbxVals[i];
        gb.Controls.Add(radbtn);
    }
    return gb;
}

UPDATE

The idea in the answer below by Pierre seems sensible, but it's still not quite what the doctor ordered:

enter image description here

UPDATE 2

This works pretty well (modification of Pierre's code):

IList<string> grpbxVals = new List<string>(currentSettings.Split('~'));
GroupBox gb = new GroupBox { Height = 60, Location = new Point(curLeftVal, 0) };

int radButtonPosition = 0; 
for (int i = 0; i < grpbxVals.Count() - 1; i++)
{
    gb.Controls.Add(new RadioButton { Text = grpbxVals[i], Location = new Point(curLeftVal, radButtonPosition) });
    radButtonPosition += new RadioButton().Height - 4; // the "-4" is a kludge
}
return gb;

Gives me:

enter image description here

2
Works fine here i.imgur.com/kslsOaK.png. Don't know why you have an offset, and 60px height won't be enough for 3 items, it fits about 2.5. Looks like your starting Y is a little off, adjust it if necessary, I used the same as your groupbox.Pierre-Luc Pineault
Both your refactored version and FYI's version produce the exact same look as the last scream shot above.B. Clay Shannon
Adjust Y as you need, start by adding 10 pixels and rise it until it gets the desired aspect. Also, you can use a FlowLayoutPannel instead of the group box (or combined), in this way it will auto-position the items and you will not need to worry about it.Gusman
It definitely sounds like I've should have gone with the FlowLayoutPanel; I forgot all about that critter.B. Clay Shannon

2 Answers

1
votes

If you set a breakpoint, you'll see that your groupbox contains all the radiobuttons. Their location is indeed all the same, so they're displayed one above the other. The problem is not adding them all to the groupbox, but displaying them all.

To achieve that, simply increment their location on each add operation to display them all :

private GroupBox getGroupBox(string currentSettings, int curLeftVal)
{
    // "apple~orange~peach~True (must look for "enclose group in a black box" as the last val (ignore for the quick-and-dirty mockup, though))
    List<string> grpbxVals = new List<string>(currentSettings.Split('~'));
    GroupBox gb = new GroupBox();
    gb.Height = 60;
    gb.Location = new Point(curLeftVal, PANEL_TOP_LOC);
    RadioButton radbtn = null;
    // "-1" because we're ignoring the final bool ("enclose in black box")
    int radButtonPosition = PANEL_TOP_LOC;
    for (int i = 0; i < grpbxVals.Count - 1; i++)
    {
        radbtn = new RadioButton();
        radbtn.Text = grpbxVals[i];
        radbtn.Location = new Point(curLeftVal, radButtonPosition );
        radButtonPosition += radbtn.Height;
        gb.Controls.Add(radbtn);

    }
    return gb;
}

I'm defining a variable called radButtonPosition and initializing it to your groupbox's position. I'm then setting the radiobutton location according to it and then simply incrementing that radButtonPosition by the height of a radiobutton each time one is added.

Here's also a little refactored version :

private GroupBox CreateGroupboxWithRadiobuttons(string currentSettings, int curLeftVal)
{
    IList<string> grpbxVals = new List<string>(currentSettings.Split('~'));
    GroupBox gb = new GroupBox { Height = 60, Location = new Point(curLeftVal, PANEL_TOP_LOC) };

    int radButtonPosition = PANEL_TOP_LOC;
    for (int i = 0; i < grpbxVals.Count() - 1; i++)
    {
        gb.Controls.Add(new RadioButton {Text = grpbxVals[i], Location = new Point(curLeftVal, radButtonPosition)});
        radButtonPosition += new RadioButton().Height;
    }

    return gb;
}

There's of course a LOT of method extraction to do to respect SRP, but that's a start.

1
votes

All the items are a Location 0,0 Try this

int y=20;
for (int i = 0; i < grpbxVals.Count-1; i++)
    {
        radbtn = new RadioButton();
        radbtn.Text = grpbxVals[i];
        radbtn.Location=new System.Drawing.Point(6, y);
        y+=radbtn.Height;
        gb.Controls.Add(radbtn);
        radbtn = null;
    }

Also can insert a FlowLayoutPanel inside the GroupBox, then add the RadioButton to the FlowLayoutPanel, for a automatic placement of the components