Question Trying to Pass a groupbox to get radio button text

lovekeiiiy

Member
Joined
Dec 29, 2013
Messages
12
Programming Experience
Beginner
I'm working on trying to understand classes better. I didn't feel like I got a good grasp of it in my programming class last semester. So, I'm using a textbox for a different class (Visual Basic) for the no-nothing assignments design to reinforce the lesson.


Anyway, I'm a bit stuck. I tried doing a search on the web, and just couldn't find the answer to get me over the hump. I also tried asking on another forum, not specifically focused on C# (Linky), but did not get a response. The assignment is to create some conference registration form. Form design was given. Also said to use a three-tier program design. There is a checkbox for preconferences, when checked shows three conference choices (each is course is the same fee).


What I did was create classes for the form, validating data, and database. What I was thinking I could do was pass the groupbox and the controls within it (three radio buttons). Then I could check to make sure the user picks one (passing to validation class), and get the radio button text to write to the text delimited file (passing to the database class). I've passed the groupbox, I think, but it's not letting me access the controls.


Here's the code to show what I was doing. I may have included some extra, unneeded information. I just wasn't sure.


I've create a class to create an object to hold customer information.
C#:
namespace NetworkConferenceRegistration
{
    public class ConferenceRegistraction
    {
        //fields
        private int corpID;
        private string firstName;
        private string lastName;
        private int days;
        //private string conferenceName;


[removed code]


        //constructor
       public ConferenceRegistraction(int intCorpID, string strFirstName, string strLastName, int intDays, GroupBox grpCourses)
        {
            corpID = intCorpID;
            firstName = strFirstName;
            lastName = strLastName;
            days = intDays;
            conferenceName = grpCourses.Controls.OfType<RadioButton>;
            
        }

        public ConferenceRegistraction(int intCorpID, string strFirstName, string strLastName, int intDays, RadioButton radCourse)
        {
            corpID = intCorpID;
            firstName = strFirstName;
            lastName = strLastName;
            days = intDays;
            conferenceName = radCourse.Text;
         }

        //properties
        public int CorpID
        {
            get
            {
                return corpID;
            }
            set
            {
                corpID = value;
            }
        }
        public string ConferenceName
        {
            get
            {
                
                return ConferenceName;
            }
        }



[removed code] 
        
        public string ConferenceName //readonly.  don't think i'll need to set which radio button to use or change its text property
        {
            get
            {
                
                return ConferenceName;
            }
        }
                        
        //calculate conferense cost
        public decimal GetCost(CheckBox chkPreconference)
        {
            //local variables
            const decimal decConferenceRatePerDay = 350;    //conference rate per day
            decimal decConferenceCost = 0;                     //total cost of conference


            //calculate the cost based on number of days
            decConferenceCost = decConferenceRatePerDay * Days;
            
            //add preconference cost
            if (chkPreconference.Checked == true)
            {
                decConferenceCost += 675;
            }
            return decConferenceCost;
        }
    }
}


the form
C#:
namespace NetworkConferenceRegistration
{
    public partial class frmNetworkRegistraction : Form
    {
       [code removed]


        //get user information and calculate costs
        private void btnCalculateCosts_Click(object sender, EventArgs e)
        {
            //check to see if user data is valid
            if (txtCorpID.MaskFull & //did user input ID number
                Validation.IsDataEntered(txtFirstName, "First Name", ref strErrorMessage) &   //did user enter first name
                Validation.IsDataEntered(txtLastName, "Last Name", ref strErrorMessage) &    //did user enter last name
                Validation.IsDataEntered(txtNumberOfDays, "Number of Days", ref strErrorMessage) & //did user enter number of days
                Validation.IsDataWithinRange(txtNumberOfDays, 1, 4, "Number of Days", ref strErrorMessage) == true)    //is number of days four or less
            {
                //create object and instantation
                ConferenceRegistraction objNewConferenceRegistraction = new ConferenceRegistraction(Convert.ToInt32(txtCorpID.Text.Trim()), txtFirstName.Text.Trim(), txtLastName.Text.Trim(), Convert.ToInt16(txtNumberOfDays.Text.Trim()));
                lblTotalCosts.Text = objNewConferenceRegistraction.GetCost(chkPreConferenceCourse).ToString();
            }
            else
            {
                MessageBox.Show(strErrorMessage, "Input Error");
                
                //reset error message
                strErrorMessage = string.Empty;
            }
        }
[code removed]


       //change form to display preconferences course selection or not
        private void chkPreConferenceCourse_CheckedChanged(object sender, EventArgs e)
        {
            if (this.grpCourses.Visible == false)
            {
                this.grpCourses.Visible = true;
            }
            else
            {
                this.grpCourses.Visible = false;
            }
        }
    }
}


I have worked on this more, working the database class/tier, and I'm getting, an StackOverFlowException was unhandled error. I figured this error is tied to my issue of not being about the pass which radio button selected and text into ConferenceRegistration class. If I code out the ConferenceName line, it works fine.

C#:
namespace NetworkConferenceRegistration{
    public static class Database
    {
        //class level variables
        private static string strDirectory = Application.StartupPath;
        private static string strFileName = "/ConfereenceRegistration.txt";


        public static void Save(ConferenceRegistraction conferenceInformation)
        {
            //create output stream and file
            StreamWriter outputInformation = new StreamWriter(new FileStream(strDirectory + strFileName, FileMode.Create, FileAccess.Write));
            outputInformation.Write(conferenceInformation.CorpID + ",");
            outputInformation.Write(conferenceInformation.FirstName + ",");
            outputInformation.Write(conferenceInformation.LastName + ",");
            outputInformation.Write(conferenceInformation.Days + ",");
            outputInformation.Write(conferenceInformation.ConferenceName + "\n");


            //close file
            outputInformation.Close();
        }
    }
}

Any help or suggestions will be appreciated. Thanks in advance.
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,272
Location
Sydney, Australia
Programming Experience
10+
Is that ConferenceRegistraction class in your presentation layer or your service (business logic) layer? If it's in the middle layer then it must not know anything about the presentation layer and controls are specifically presentation. If you have a middle layer performing validation then the presentation layer must package the data in some form that is not reliant on any particular presentation technology.
 

lovekeiiiy

Member
Joined
Dec 29, 2013
Messages
12
Programming Experience
Beginner
I'm not quite sure where the ConferenceRegistration class fits, but I think it would be business tier. My thinking was to have it create an object that holds a person's registration information--ID, first name, last name, number of days, total cost, and (if applicable) preregistration course name. Then use that object to pass to the database to be saved.

I was trying to set it up that the information be validating before creating the object. I do have a specific Validation class I created. It confirms names are not numbers, days and ID are integers and within acceptable ranges, all entry fields have data.

The presentation tier, specifically the form, I did not design. It was given in the assignment.
mockup.jpg If the user checks the Take Pre-Conference Course, then the Courses Groupbox appears; it is not shown by default.

Given that it's possible a person can register without taking a preconference course, I assume it would be possible to create an object that would have just an null field or empty string, so when the registration is saved, it would just have a blank field in the comma delimited text file in those situations.

Unfortunately, I was not given a lot of examples of how to use the three tier program structure. Sounds like I may have some misunderstandings. Any suggestions on what would be a better method? I assume creating an object for the registration is appropriate, but how I'm passing information to get the information to ConferenceRegistration class is off.

Thanks for again.
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,272
Location
Sydney, Australia
Programming Experience
10+
The first thing to consider when designing an n-tier application is that, while it's not necessary, it's possible that each tier will be in a different physical location. If your service layer is on a server on the other side of the world to your presentation layer, which is a possibility, then you don't want to be passing a complex object like a GroupBox around just for a few values. Normally you would define a class for each entity that contains just the data for that entity. You can then populate an instance of that class at the UI and pass it down through the layers as required and you're passing the minimum data possible. You might do some validation at the UI but it's always good form to validate at the service layer because it might be used with different presentation layers or even automated tools to import data in bulk.
 

lovekeiiiy

Member
Joined
Dec 29, 2013
Messages
12
Programming Experience
Beginner
None of that was discussed in class or my textbooks. The first thing that comes to mind is that I probably should not pass a checkbox either. I did this as well in the ConferenceRegistration class GetCost method, which is used to calculate the cost of the registration. Since all preconference courses were all the cost, I just needed to know if that was checked to add the added fix cost.

So, would it be better to setup optional parameters and give default values, such as preconference cost ($0) and name (empty string). If so, would one then create a variable in the form class to get the value if the checkbox is checked and which radio button (or property value) is selected?
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,272
Location
Sydney, Australia
Programming Experience
10+
I'm not sure what you mean about optional parameters and default values. You define a class to represent an entity and then you populate the properties of an instance of that class from the controls in the UI. You then validate those properties as appropriate, e.g. that strings are not empty and that numbers are in required ranges.
 

lovekeiiiy

Member
Joined
Dec 29, 2013
Messages
12
Programming Experience
Beginner
Sorry, not that I know it better, but I'm have more familiarity in Visual Basic. I thinking maybe it possible, like with setting up a method signature, creating optional parameters, where you have give a default value, which can be changed when you pass an value in the calling statement. I found this link on the MSDN site: Named and Optional Arguments (C# Programming Guide).

I'm just not finding or seeing a solution of creating precourse name element in the ConferenceReference object from the ConferenceReference class because there isn't always a value for it. I'm think I need to have the property and some kind of value (null, empty string, or maybe a literal string "none selected") because the database creates comma delimited textfile with the registration information. I'm assuming the textfile will hold several registrations, which some will have preconference courses and others not. Right now, I get an exception when it tries to save the file with no preconference course name value
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,272
Location
Sydney, Australia
Programming Experience
10+
Right now, I get an exception when it tries to save the file with no preconference course name value

Perhaps we could help you with that issue if we knew what the exception was and the code that threw it.
 

lovekeiiiy

Member
Joined
Dec 29, 2013
Messages
12
Programming Experience
Beginner
I thought I had mentioned in the my OP. The exception I'm getting is StackOverFlowException was unhandled error. Here is the Database class code.
C#:
[COLOR=#333333]namespace NetworkConferenceRegistration{[/COLOR]
    public static class Database
    {
        //class level variables
        private static string strDirectory = Application.StartupPath;
        private static string strFileName = "/ConfereenceRegistration.txt";


        public static void Save(ConferenceRegistraction conferenceInformation)
        {
            //create output stream and file
            StreamWriter outputInformation = new StreamWriter(new FileStream(strDirectory + strFileName, FileMode.Create, FileAccess.Write));
            outputInformation.Write(conferenceInformation.CorpID + ",");
            outputInformation.Write(conferenceInformation.FirstName + ",");
            outputInformation.Write(conferenceInformation.LastName + ",");
            outputInformation.Write(conferenceInformation.Days + ",");
            [B]outputInformation.Write(conferenceInformation.ConferenceName + "\n");[/B]


            //close file
            outputInformation.Close();
        }
    } [COLOR=#333333]}[/COLOR]

I tried bolding the line that Visual Studio detects the error. If I code out the line, there are no issues. I can't remember if I tried giving it a string, since that is what the conference name would be, and what happened. Overall, it still ties into creating the preconference course name text element of the RegistrationConference object. Other than that, I think I may want to change from Write to Append, but for the assignment, it may not matter since I don't know how this program ties into scheme and how the file will be access or used to retrieve information.
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,272
Location
Sydney, Australia
Programming Experience
10+
If you have a stack overflow then that ConferenceName property must be executing code that ends up getting the same property and so one for ever. Look at the stack trace of the exception and see what course execution is taking and then you can determine what exactly to do about it.
 

lovekeiiiy

Member
Joined
Dec 29, 2013
Messages
12
Programming Experience
Beginner
Well, I looked at the Stacktrace and didn't make a lot sense to me. But local value window had an error about not having a value. I was more expecting something to that nature because I don't think I wasn't assigning a value to the conference registration object property. I have fixed it overall.

I added some code in the form class that if the precourse check is checked or not, it will either pass the radio button's text from it's text property or no text (empty string).

C#:
private void btnCalculateCosts_Click(object sender, EventArgs e)        {
            //check to see if user data is valid
            if (txtCorpID.MaskFull & //did user input ID number.
                Validation.IsDataEntered(txtFirstName, "First Name", ref strErrorMessage) &   //did user enter first name
                Validation.IsDataEntered(txtLastName, "Last Name", ref strErrorMessage) &    //did user enter last name
                Validation.IsDataEntered(txtNumberOfDays, "Number of Days", ref strErrorMessage) & //did user enter number of days
                Validation.IsDataWithinRange(txtNumberOfDays, 1, 4, "Number of Days", ref strErrorMessage) == true)    //is number of days four or less
            {
                string strCourseName = string.Empty;
                if (chkPreConferenceCourse.Checked == true)
                {
                    //foreach (Control button in grpCourses)
                    //{
                    //}
                }
                else
                {
                    //strCourseName = "no precoure taken";
                }


                //create object and instantation
                ConferenceRegistraction objNewConferenceRegistraction = new ConferenceRegistraction(Convert.ToInt32(txtCorpID.Text.Trim()), 
                    txtFirstName.Text.Trim(), txtLastName.Text.Trim(), Convert.ToInt16(txtNumberOfDays.Text.Trim()), strCourseName);
                lblTotalCosts.Text = "Total conference cost is " + objNewConferenceRegistraction.GetCost(chkPreConferenceCourse).ToString("c");


                //save registration information
                Database.Save(objNewConferenceRegistraction);
            }
            else
            {
                MessageBox.Show(strErrorMessage, "Input Error");
                
                //reset error message
                strErrorMessage = string.Empty;
            }
        }

What I'm having trouble with is finding an efficient way to get which, and if, a radio button has been selected in a group, and getting it's text property, and really the prior. I was thinking maybe some kind of foreach loop to check each radio button if checked property is true, and then get that button's text property. Unfortunately, how I have done it comes up with a build error. I did google search, and found a suggest using a radiogroup, but I couldn't find anything that explain what it was or how to use.
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,272
Location
Sydney, Australia
Programming Experience
10+
The easiest way to get that information re the RadioButtons is to use LINQ, e.g.
var selection = this.Controls.OfType<RadioButton>().SingleOrDefault(rb => rb.Checked);

if (selection == null)
{
    MessageBox.Show("No selection has been made.");
}
else
{
    MessageBox.Show(selection.Text + " selected.");
}
That goes to the Controls collection of the form, gets the controls of type RadioButton and gets the one and only RadioButton that is checked or null if there isn't one checked.
 

lovekeiiiy

Member
Joined
Dec 29, 2013
Messages
12
Programming Experience
Beginner
thanks for the reply. I've only heard about LINQ, but wasn't covered in any of the stuff I have learned about yet. I tried reading about it on the MSDN site, but was not really able to keep up with the explanations. Although, it does appear I have used it in some form in past.

Anyway, I tried the code given, but wasn't working 100%. It wasn't detecting any selected radio buttons. And do to my ignornance, I wasn't able to debug it. So, I went less efficient and got it working.
C#:
string strCourseName = string.Empty;                if (chkPreConferenceCourse.Checked == true)
                {
                    if (radMovingBitsBytesCourse.Checked == true)
                    {
                        strCourseName = radMovingBitsBytesCourse.Text;
                    }
                    else if (radNetworkSecurityCourse.Checked == true)
                    {
                        strCourseName = radNetworkSecurityCourse.Text;
                    }
                    else if (radWANCourse.Checked == true)
                    {
                        strCourseName = radWANCourse.Text;
                    }
                    else
                    {
                        MessageBox.Show("No precourse was selected", "Input Error");
                    }
                }

There is a logic error, but it's more on me than the code. I shouldn't have it create the ConferenceRegistration object if no course is selected since it would have invalid data. I could either have of the courses selected by default; probably the easiest fix. Another option could be to create a method within the form and just call it after retrieving the radio button text statement. I'm not fond of this since I would be repeating the same line three times.
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,272
Location
Sydney, Australia
Programming Experience
10+
Most likely the LINQ didn't work because you just used the code directly from my example. That example uses the Controls collection of the form but, If I recall, your RadioButtons are children of a GroupBox rather then the form itself.
 

lovekeiiiy

Member
Joined
Dec 29, 2013
Messages
12
Programming Experience
Beginner
Yes, I copied the code you gave. Yes, the radio buttons were in a groupbox.

I must have ran into an issue and found, and fixed, the ConferenceName property. I have returning the conferenceName field. Thanks for pointing it out nonetheless.
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,272
Location
Sydney, Australia
Programming Experience
10+
Yes, I copied the code you gave. Yes, the radio buttons were in a groupbox.

I must have ran into an issue and found, and fixed, the ConferenceName property. I have returning the conferenceName field. Thanks for pointing it out nonetheless.

It's often said that relying on case alone to distinguish indentifiers is bad practice. I code a lot in VB too and it is not case-sensitive so I usually prefix a field that backs a property with an underscore, which is not uncommon for VB developers. For clarity, I use the same convention in C#.
 

lovekeiiiy

Member
Joined
Dec 29, 2013
Messages
12
Programming Experience
Beginner
agreed. I definitely like, and prefer, the use of prefixes. It makes it so much easier to know what the variable is and how it's being used. I also started learning VB first (and I do remember seeing your avatar name over in the vbforums too).

I'm still learning, so I'm bound to make a few, or more errors. Hopefully, I'm able to learn from them.
 
Top Bottom