CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 15

Hybrid View

  1. #1
    Join Date
    Mar 2009
    Posts
    15

    A couple of radio button questions

    I have two questions regarding radio buttons. I'm using Visual Studio 2008 Express with the targeted .Net framework being 2.0. I'm also still very new to C# and just trying to learn as I go.

    My first question is that I am using CheckChanged, but I noticed that by doing that the code for not just the radio button that is checked is ran, but the code for the one that gets unchecked will run as well.

    How do I stop that from happening?

    My second question is about saving which radio buttons are checked. I have no idea about this. I want the radio buttons that the user selects to be saved so that the next time the program is opened the user doesn't have to go and reselect everything again.

    Can I use Settings.settings? If so, how? Or do I need to use something else? I've searched for this, but nothing I've come across makes sense to me.

  2. #2
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: A couple of radio button questions

    Quote Originally Posted by Vorkosigan View Post
    My first question is that I am using CheckChanged, but I noticed that by doing that the code for not just the radio button that is checked is ran, but the code for the one that gets unchecked will run as well.

    How do I stop that from happening?
    You don't. From within the CheckChanged handlers, use the Checked property to determine the state. If you only want to handle the condition where an item is checked, then check for if( Checked == true ) inside the handler.

  3. #3
    Join Date
    Mar 2009
    Posts
    15

    Re: A couple of radio button questions

    Thanks Arjay, that did the trick. I knew it had to be something simple, but just wasn't sure what.

    Another radio button question that I've been trying to figure out... I have an exception that catches when certain radio buttons on selected at the same time. It's doing exactly what i want it to do except for one thing... when it catches the exception, it still selects the radio button that caused it to be thrown.

    Is there way to keep it from being selected when the exception is thrown or to change it back to unselected when the exception is caught?

  4. #4
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: A couple of radio button questions

    Quote Originally Posted by Vorkosigan View Post
    I have an exception that catches when certain radio buttons on selected at the same time. It's doing exactly what i want it to do except for one thing... when it catches the exception, it still selects the radio button that caused it to be thrown.
    Let me start out by saying that the selection state of radio buttons within a group is mutually exclusive - meaning only one radio button within the group can be selected at a time.

    I mention this because often developers that don't understand UI design misuse a radio button and allow more than one radio button selected within the group. If more that one item can be selected in a group then a more appropriate control to use is a checkbox.

    Given the idea that radio button selection is exclusive within a group, the AutoCheck property can be used to help promote exclusivity within a group of buttons.

    Allow me to define what a group is. In Win32 programming, a group of radio buttons was a series of radios in consecutive tab order with the first button's group style set to true. So let's say that there are 5 consecutive radio buttons (consecutive by tab order) and the 1st and 4th radio buttons had their group property set to true. We would end up with two groups of radio buttons (G1 == 1,2,3; G2 == 4,5). If only the 1st radio button had the group set to true, then all 5 radio buttons would be in the group.

    In .Net Radio buttons are grouped differently. They are grouped based on the control that contains them. Unfortunately, there isn't a 'Group' property to control whether a series of radio buttons can be broken into separate groups.

    In .Net, groups are controlled by the parent control. If 3 radio buttons are children of the form, then they will all be part of the same group. If you have 5 radio buttons and you want to have two groups, then you'll need to make some of the radio buttons children of another control (within the form). GroupBox and Panel controls make excellent control containers to group radio buttons.

    So to review, if you set the AutoCheck property to true for each radio button within a 'group', then the framework will automatically check the selected button (and uncheck any previous radio button for you).

    So now that we have the 'visual' part taken care of. Let's discuss how to determine which radio button within a 'group' has been selected. To do this, we borrow the concept from MFC and it's DDX mechanism. In MFC, radio buttons with a consecutive tab order and the 1st button has the group style set to true can use the DDX variable mechanism to wire up an integer that gets set to the zero-based index of the selected radio button within the group (or -1 if no radio buttons are selected).

    This is pretty cool because, you don't need to enumerate each button and check if it's been selected. All you need to do is check one integer variable.

    Unfortunately, .Net doesn't have this feature builtin. The good news is that it isn't hard to implement. It just takes two methods: One to retrieve the index of the selected radio button within the group and another method to clear the selected state within the group.

    All you need to do is pass in the parent control that contains the radio buttons. Remember the parent control is what defines radio buttons within a group. Radio buttons with different control parents are considered to be in different groups.

    Code:
    #region  Radio  Button  Helper  methods
     
    privatevoid   ClearRadioButtonsInGroup( Control parent )
    {
      foreach ( Control child in parent.Controls )
      {
        RadioButton radio = child asRadioButton;
     
        if ( radio != null )
        {
          radio.Checked = false;
        }
      }
    }
     
    ///<summary>
    /// Returns a zero-based index of the selected radio
    /// button within the group.
    ///</summary>
    ///<param name="parent">Control which contains the radio buttons</param>
    ///<returns>Index of selected radio button; -1 if none are selected</returns>
    privateint GetSelectedRadioIndex( Control parent )
    {
      int index = NoneSelectedIndex;
     
      var radioButtons = newSortedDictionary< int, RadioButton >( );
     
      // Add the radio buttons to the dictionary
      // sorted by tab index
      foreach ( Control child in parent.Controls )
      {
        RadioButton radio = child asRadioButton;
     
        if ( radio != null )
        {
          radioButtons.Add( radio.TabIndex, radio );
        }
      }
     
      // Walk through the dictionary (which are 
      // sorted by tab index) to retrieve the index
      // of the selected radio button.
      // NOTE: The first index within this group
      // will always be 0 regardless of the starting
      // tab index. This is done so you know that
      // 0 always represent the first radio button
      // within the group
      foreach ( int tabIndex in radioButtons.Keys )
      {
        index++;
     
        if ( radioButtons [ tabIndex ].Checked )
        {
          return index;
        }
      }
     
      return NoneSelectedIndex;
    }
     
    #endregion Radio Button Helper methods
     
    privatereadonlyint NoneSelectedIndex = -1;
    See the attached project for a sample that contains 3 radio buttons 'grouped' within a GroupBox control and 2 radio buttons 'Grouped' by the form. The sample also contains buttons to clear the selections by group and when the OK button is hit, the selected values of the radio button groups are displayed.
    Attached Images Attached Images   
    Attached Files Attached Files
    Last edited by Arjay; March 3rd, 2010 at 12:21 PM.

  5. #5
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: A couple of radio button questions

    To follow up, I find the approach outlined above to be easier that trying to manually track the states using the CheckChanged events. Of course, not always will the above approach be sufficient (but that isn't to say that you can combine both approaches).

    Btw, here is the code to retrieve the selected radio buttons when the OK button is pressed.
    Code:
    private  void   btnOK_Click( object sender, EventArgs e )
    {
      Colors color = (Colors) GetSelectedRadioIndex( this.groupBox1 );
      Sizes size = (Sizes) GetSelectedRadioIndex( this );
     
      MessageBox.Show( String.Format( "Selected Color: {0}\nSelected Size: {1}", color, size ) );
    }


  6. #6
    Join Date
    Mar 2009
    Posts
    15

    Re: A couple of radio button questions

    I'm gonna take another look at this tomorrow when I am more awake so that I can fully understand what you are trying to tell me, but so far it looks like it's more complex than I was thinking it should be.

    I'll try to describe what I am doing a little better. I have 5 panels as my containers. 4 of those panels have 5 radio buttons. The other one has 6 radio buttons. One of the buttons in each panel is set as a "default" to have no value. Each panel has it's own variables that get assigned depending on the radio button that is selected. That part works just fine.

    Where the problem comes in is a little hard to explain. There's another variable that needs to be taken into consideration that can only come from adding up a number that is based on which radio buttons are selected across all of those panels.

    So for this other variable, the first four radio buttons in the first 4 panels are valued at 2, 3, 4 and 5. The first 5 radio buttons of the last panel are valued at 2, 4, 6, 8 and 9. These are separate values from the variables that get assigned when the radio buttons are checked.

    The total of these secondary values can only add up to 9. This is where the problem is. If some checks the 5th radio button of the 5th panel, they are already at 9. So I have an exception that is thrown when they then try to select another radio button that makes that total go over that number. That pops up a message stating that the total can't go over 9, but it still lets the radio button get checked.

    I'm sure it seems pretty awkward, but I hope that's a clearer picture of what I am trying to do and why.

  7. #7
    Join Date
    Jan 2010
    Posts
    1,133

    Re: A couple of radio button questions

    Just a thought: If the selected radio button of a group needs to be tracked, why not to just add a member variable for each group (or create a simple RadioButtonGroup class with such a field/property) that would always reference to it, and that would be updated inside the CheckChanged event handler?

    Something like:

    Code:
    private RadioButton current = null;   // This can also be set to initially point to the default option...
    
    // ...
    
    private void radioButton_CheckedChanged(Object sender, EventArgs e)
    {
        RadioButton rBtn = (RadioButton)sender;
    
        if (rBtn.Checked)
            current = rBtn;
            
        // ...
    }
    (All the radio buttons of a group should use the same handler method in this case.)

    For additional details, one could use Text and/or Tag properties of RadioButton class.
    Last edited by TheGreatCthulhu; March 3rd, 2010 at 03:13 PM. Reason: Forgot to add if (rBtn.Checked) part...

  8. #8
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: A couple of radio button questions

    Quote Originally Posted by TheGreatCthulhu View Post
    Just a thought: If the selected radio button of a group needs to be tracked, why not to just add a member variable for each group (or create a simple RadioButtonGroup class with such a field/property) that would always reference to it, and that would be updated inside the CheckChanged event handler?

    Something like:

    Code:
    private RadioButton current = null;   // This can also be set to initially point to the default option...
     
    // ...
     
    private void radioButton_CheckedChanged(Object sender, EventArgs e)
    {
        RadioButton rBtn = (RadioButton)sender;
     
        if (rBtn.Checked)
            current = rBtn;
     
        // ...
    }
    (All the radio buttons of a group should use the same handler method in this case.)

    For additional details, one could use Text and/or Tag properties of RadioButton class.
    That sounds pretty good until you need to track several groups of radio buttons that have dependencies and conditions - then the whole thing becomes unwieldy pretty fast.

    IMO, programming using Text and/or Tag is a more like an asp scripting hack.

  9. #9
    Join Date
    Jan 2010
    Posts
    1,133

    Re: A couple of radio button questions

    Quote Originally Posted by Arjay View Post
    IMO, programming using Text and/or Tag is a more like an asp scripting hack.
    Well, OK, I agree about the Text property, but only partially about the Tag.
    Sure, Tag can be misused, but I think it's OK to use it for tag-like data (integer index, or string description, or enum), or helper-data, or convenient additional data. I'm not saying that it should be used often, but when used as intended, I don't see why it would be considered a hack.

    I, of course, respect your opinion, and your experience, but I still don't see how the interdependency could be so complex that a class based approach couldn't handle it (with a class to represent a radio button group).

    I combined my idea with what you suggested, and the attached zip is what I came up with. I added some Size-option related behavior to spice it up a bit (one of the labels on the right provides a fictional remark for certain color/size combinations).

    The rough design is shown in the attached image.
    The RadioButtonGroup class tracks the current selection (if any), and provides a way to get the index of the selected radio button. The buttons are sorted by tab index (I chose to use SortedList<> instead of SortedDictionary<>).
    There is an event fired whenever the state of the group is changed, and handlers are provided with all means necessary to do the app logic.

    There is a potential problem with the AutoSelect property of the RadioButton class, since the RadioButtonGroup class relays on the assumption that clients won't change it, but it can be prevented one way or another, I didn't have time to deal with it.

    The dialog has properties which enable the client to check the choices that were made after the dialog is closed.

    This probably needs more work, but it's only to demonstrate the concept.
    And, by the way, the Tag property is not used

    Quote Originally Posted by Arjay View Post
    That sounds pretty good until you need to track several groups of radio buttons that have dependencies and conditions - then the whole thing becomes unwieldy pretty fast.
    I would appreciate if you could show me a scenario where this approach wouldn't work well.

    P.S. Sorry if the code is not documented/commented enough; I suppose that, given this discussion, it's more or less self-explanatory.
    Attached Images Attached Images  
    Attached Files Attached Files
    Last edited by TheGreatCthulhu; March 4th, 2010 at 12:40 PM. Reason: The P.S., and a thing or 2 to add.

  10. #10
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: A couple of radio button questions

    TheGreatCthulhu, nice job on the alternate approach.

    Expanding on both approaches, I wonder if it wouldn't be helpful to create a user control that encapsulates the functionality?

  11. #11
    Join Date
    Jan 2010
    Posts
    1,133

    Re: A couple of radio button questions

    Thanks.
    I suppose it could prove to be useful.
    I’ve been considering the concept in my spare time, doing some experimentation; I think that this type of control shouldn’t limit the users’ freedom to create their own arrangement of child controls (radio buttons), by forcing a certain layout or something alike.
    I’ve been trying to find a good approach (at least as far as the design is considered), and what I feel is right is that this should be some sort of a Panel-like container control - a UserControl specialized for radio buttons and related tasks. The user would be able to use the IDE to drag & drop any child control, and any RadioButton control would receive a special treatment.

    I’ve somewhat altered the RadioButtonGroup class from my previous post to suit this new problem, and created a UserControl-derived RadioButtonContainer on top of that.
    As I’ve said, the AutoCheck property might introduce some problems, so in this implementation I chose to ignore it completely, without ever changing it.

    However, the ability to dynamically add/remove radio buttons generates a new set of problems, as does the designer feature. It is mainly related to the fact that the radio buttons are sorted by tab index, and that the user can alter any of the indices after the buttons have been added to the RadioButtonContainer (at run-time, or at design-time...).
    So, I added the TabOrderChanged event, and the Sort() method.

    I overrided the OnLoad() method of RadioButtonContainer to ensure that if the user changed the tab order in the designer, the buttons will be reordered (by calling Sort()). But, now I think this was a wrong decision , since it makes the control harder to use and somewhat unpredictable (I had some problems with an instance of this class that is a child to a inactive TabPage control – the OnLoad() is not called until this tab page is shown – so one can’t rely on it). This is probably a task that should be completed at the design time by the custom designer.

    Anyway, the RadioButtonGroup does all or most of the work, and other types of controls may be created to reuse this functionality.
    In the test project, there’s a bunch of radio buttons inside 4 RadioButtonContainer controls. The radio buttons represent options for the creation of a fantasy game caracter. The last two of the radio buttons in the Magic group box both have AutoCheck set to false, to demonstrate that this property is not used. This one, and other RadioButtonContainer controls show how they can conveniently be nested into other standard controls using docking. The ones inside the TabControl show that a RadioButtonContainer may contain other controls without any problems, and that it can be used with other child controls at the same level in the hierarchy.

    I was just playing with the idea – so this needs a significant amount of testing and refinement. For example, I didn't consider thread safety issues. Documentation could be improved also. The attached class diagram shows all the significant methods, though.

    P.S. To anyone who might find this code useful: you are free to use and modify it.
    Attached Images Attached Images  
    Attached Files Attached Files

  12. #12
    Join Date
    Mar 2009
    Posts
    15

    Re: A couple of radio button questions

    Thanks guys. I'm still trying to wrap my head around it. I haven't been able to focus on it as much as I would like at the moment.

    It would appear that it's above my current level of knowledge, so I'll have to go through it all and try to figure out what's doing what to make sure I get a good grasp of what's going on.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured