5

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 :-)

grady
  • 12,281
  • 28
  • 71
  • 110

3 Answers3

6

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
  • 28,277
  • 7
  • 90
  • 101
  • 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 May 25 '10 at 10:32
  • 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 May 25 '10 at 10:34
  • 1
    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 May 25 '10 at 10:36
  • 2
    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 May 25 '10 at 10:37
3

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
  • 98,240
  • 88
  • 296
  • 433
1

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
  • 3,477
  • 23
  • 37
  • 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 May 25 '10 at 16:27