Colin
Colin

Reputation: 35

Multiple Checkboxes and enumeration

I am having troubles getting my head wrapped around how this should be done. I have 3 check boxes on a form that are to be input into a constructor. I am creating a variable to pass this information into the constructor. Listed below some of the code

public enum Accessories
    {
        None,
        StereoSystem,
        LeatherInterior,
        StereoAndLeather,
        ComputerNavigation,
        StereoAndNavigation,
        LeatherAndNavigation,
        All
    }

        SalesQuote.Accessories accessoryChosen;

        if(!chkStereoSystem.Checked && !chkLeatherInterior.Checked && !chkComputerNavigation.Checked)
            {
                accessoryChosen = SalesQuote.Accessories.None;
            }
            else if(chkStereoSystem.Checked && !chkLeatherInterior.Checked && !chkComputerNavigation.Checked)
            {
                accessoryChosen = SalesQuote.Accessories.StereoSystem;
            }

Am sure there is an much cleaner way to do this.

Upvotes: 1

Views: 922

Answers (3)

The One
The One

Reputation: 4696

You could use the RadioButton's Tag Property (assuming Papa's comment is right)

In the constructor of the form:

    chkStereoSystem.Tag = Accesories.StereoSystem;
    chkLeatherInterior.Tag = Accesories.LeatherInterior;
    chkComputerNavigation.Tag = Accesories.ComputerNavigation;

And whenever you need the selected one:

 SalesQuote.Accessories accessoryChosen =(Accessories) yourForm.Controls.OfType<RadioButton>()
                                  .FirstOrDefault(r => r.Checked).Tag;

If no RadioButton was selected, FirstOrDefault will return 0, it will give you the first element of the enum: None

Upvotes: 1

TaW
TaW

Reputation: 54453

You should explicitly set the flag values:

public enum Accessories
{
    None = 0,
    StereoSystem = 1,
    LeatherInterior = 2,
    StereoAndLeather = 3,
    ComputerNavigation = 4,
    StereoAndNavigation = 5,
    LeatherAndNavigation = 6,
    All = 7
}

Now you can calculate the chosen accessories like this:

Accessories accessoryChosen = (Accessories) 
 ((chkStereoSystem.Checked ? 1 : 0)  +
  (chkLeatherInterior.Checked ? 2 : 0) +          
  (chkComputerNavigation.Checked ? 4 : 0) ) ;

Here the flag values would be the same without writing them out, but this should be done for clarity!

Update: As Nadia points out the Enum need not enumerate all combinations.

If more Accessories come up this would get really awkward.

Let's add just two more

WarpDrive = 8,
FluxCompensator = 16,

This would bring up the number of combinations up to 32! Ouch!

Instead leave the combinations either all out or include only a few really important combinations as the link in Nadia's comment advises.

Now you will need to query for an Accessory. Using bitwise arithmetic you can write a helper function:

bool Has(Accessories Chosen, Accessories Target)
{
    return (Chosen & Target) != Accessories.None;
}

or, assuming they are sitting in a class Order or Car you can add a class function:

bool Has(Accessories Target)
{
    return (this.ChosenAccessories & Target) != Accessories.None;
}

You can also add the [FlagsAttribute] if you want the combinations to show nice lists of their values when displayed as strings.

Upvotes: 3

Nadia Chibrikova
Nadia Chibrikova

Reputation: 5036

You may make your enum flags, and then you won't have to have all combinations in the enum, but instead use | to combine then in a variable:

[Flags]public enum Accessories
{
    None=0,
    StereoSystem = 1,
    LeatherInterior =2,
    //StereoAndLeather = StereoSystem | LeatherInterior ,
    ComputerNavigation = 4,
    //StereoAndNavigation = StereoSystem | ComputerNavigation ,
    //LeatherAndNavigation = LeatherInterior | ComputerNavigation,
    All =  StereoSystem | LeatherInterior | ComputerNavigation
}

accessoryChosen =  Accessories.None;
if(chkStereoSystem.Checked )
       accessoryChosen |= Accessories.StereoSystem ;//You can add all flags this way, accessoryChosen will contain them all


if( (accessoryChosen & Accessories.StereoSystem) == Accessories.StereoSystem) 
    ...//StereoSystem was chosen

Thus if you'll have to add some new types of accessories, you'll have all additional combinations automatically.

Upvotes: 2

Related Questions