views:

63

answers:

3

Hi, I have 6 buttons on my GUI. The visibility of the buttons can be configured via checkboxes. Checking the checkbox and saving means the correpsonding button should be shown. I am wondering if it is somehow possible to have one TinyInt column in the database which represents the visibility of all 6 buttons.

I created an enum for the buttons, it looks like that:

public enum MyButtons
{
    Button1 = 1,
    Button2 = 2,
    Button3 = 3,
    Button4 = 4,
    Button5 = 5,
    Button6 = 6
}

Now I am wondering how to say that for example only button1, button5 and button6 are checked using this one column. Possible at all?

Thanks :-)

+6  A: 

Use a flags enum instead:

[Flags]
public enum MyButtons
{
    None = 0
    Button1 = 1,
    Button2 = 2,
    Button3 = 4,
    Button4 = 8,
    Button5 = 16,
    Button6 = 32
}

Then any combination of buttons is also a unique value - e.g. Button 1 & Button3 == 5

When setting the value use the binary 'or' operator (|):

MyButtons SelectedButtons = MyButtons.Button1 | MyButtons.Button3

To find out if a button is selected use the binary 'and' operator (&):

if (SelectedButtons & MyButtons.Button1 == MyButtons.Button1)... 

The reason this works becomes obvious when you think of the binary representations of the numbers:

MyButtons.Button1 = 000001
MyButtons.Button3 = 000100

When you 'or' them together you get

SelectedButtons = 000001 | 000100 = 000101

When you 'and' that with MyButtons.Button1 - you get back to MyButtons.Button1:

IsButton1Selected = 000101 & 000001 = 000001
Martin Harris
Sounds good, how do I do the saving? I mean, the column is a tinyint and how do I set all the buttons before I save them?
grady
MSDN recommends next: Use None as the name of the flag enumerated constant whose value is zero.. http://msdn.microsoft.com/ru-ru/library/system.flagsattribute.aspx
abatishchev
Once you have your SelectedButtons value, just convert it to an int and save it to the database. When you bring it back out of the database convert it back to a MyButtons enum value. There are static methods to do this on the Enum class (http://msdn.microsoft.com/en-us/library/system.enum_members.aspx)
Martin Harris
Also consider that a tinyint has a maximum value of 255 (8 bits) so you'll need a bigger column type if you have more than 8 buttons.
Martin Harris
@abatishchev Good call, edited.
Martin Harris
+3  A: 

You have to flag your enum with FlagsAttribute:

[Flags]
public enum MyButtons : byte
{
    None = 0
    Button1 = 1,
    Button2 = 1 << 1, 
    Button3 = 1 << 2, 
    Button4 = 1 << 3, 
    Button5 = 1 << 4,
    Button6 = 1 << 5
}

so you can use:

var mode = MyButtons.Button1 | MyButtons.Button5 | MyButtons.Button6;

<< means 'left-shift operator' - just a little bit more easy way to set values to enum items.

abatishchev
+1  A: 

Add the FlagsAttribute, and derive the enum from byte:

class Program {
    static void Main(string[] args) {
        MyButtons buttonsVisible = MyButtons.Button1 | MyButtons.Button2;
        buttonsVisible |= MyButtons.Button8;

        byte buttonByte = (byte)buttonsVisible; // store this into database

        buttonsVisible = (MyButtons)buttonByte; // retreive from database
    }
}

[Flags]
public enum MyButtons : byte {
    Button1 = 1,
    Button2 = 1 << 1,
    Button3 = 1 << 2,
    Button4 = 1 << 3,
    Button5 = 1 << 4,
    Button6 = 1 << 5,
    Button7 = 1 << 6,
    Button8 = 1 << 7
} 
Fredrik Johansson
One more thing: How do I know what is 1 and what is 0 after I retrieved it from the DB?--> Found the solution...see post of Martin Harris :)
grady