Store multi-choice groupbox selection in a field

D

dbuchanan

I am designing a table to contain a field to stores a value that must
indicate none, one, or many choices. The form will have a group box
with checkboxes (multi-choice)

You see the records in this table contain partially pre-configured
records. The records serve as "master" data that will later be inserted
into a data table. The master data is set up by an adminsitrator. The
administrator indicates for each record the none, one or many options
that apply to the record.

At that later time a user will want to add pre-configured records to
his/her data table. Based on the kind of project he/she will make a
selection in a group box of none, one, or many options. Then based on
that choic he/she will be presented with a filtered table displaying
the choices of pre-configured records to choose from.

Here is sample enumeration of the data that might be used as the
options to choose from.

Kitchen 1
Bathroom 2
Bedroom 4
Utility room 8
Garage 16

I know there are other approaches to achieving this, but this approach
seems the simplest. Among the reasons I think I favor this approach is
that it is not so "schema intensive".

Are there any reasons not to use this approach?

I intend to use a group box containing a list of checkboxes. When the
user makes his selection the the form adds together the values for the
selected choices to arrive at the value to store in the record.

I know there is nothing original about this approach, but I have
questions...

· What is the 1,2,4,8,16 kind of enumeration called. I hash table?
· How do I parse individual values from the sum so that I can
appropriately check or uncheck the checkboxes for the field?

And any recommendations?
 
C

Cerebrus

Hi,

1. This kind of enumeration is called a Bitfield enumeration. This is
one that supports a bitwise combination of its members. In order to
create such an enum, 2 things need to be done :
a) Mark the enum with a Flags attribute. <Flags()> in VB.NET.
b) Assign values corresponding to powers of 2 (as you did) to the
members.

2. Use Bitwise OR operation between the values. The whole advantage of
using values such as 1,2,4,8,16,32... is that the sum of any of the
values will never be equal to any other member.

For instance :
----------------------------------------------
Flags()> Public Enum TypeOfGirlFriend
None = 1
Beautiful = 2
Lovely = 4
Voluptuous = 8
End Enum

Dim myGirl as TypeOfGirlFriend = 14

Msgbox(myGirl.ToString()) ' I can tell here that the last 3 items in
my enum were chosen.

----------------------------------------------

Note that In your example, it might be wise to add a member named "All"
below Garage which in effect will be (Kitchen OR Bathroom OR Bedroom OR
Utility room OR Garage)

HTH,

Regards,

Cerebrus.
 
D

dbuchanan

Cerebrus,

Thank you,

I have a few questions;

1.) In the example you gave how can I parse out the separate values
from the number 14?

Beautiful
Lovely
Voluptuous

or

2
4
8

?

2.) What datatype should I use to store this in the database? Integer?
Byte? Binary?

3.) Are there any classes in .NET that are specifically prepared to
handle these kind of calculations?


dbuchanan
 
C

Cerebrus

Hi,

Check out the members of the Enum class for more information...

1. First, note that I could have set the myGirl variable in a different
way too :

Dim myGirl As TypeOfGirlFriend = TypeOfGirlFriend.Beautiful Or
TypeOfGirlFriend.Lovely Or TypeOfGirlFriend.Voluptuous

I assume that what you will store in your database will be the sum of
the values (14). Now, your question is how to parse the values that
have been set, from this total.

a) One way could be as simple as using the ToString() method :

Console.WriteLine(myGirl.ToString()) ' Will return
"Beautiful, Lovely, Voluptuous"
This can be then parsed as needed.

b) Secondly, you could use the Enum.Parse() method :

Console.WriteLine([Enum].Parse(GetType(TypeOfGirlFriend), "12"))
'Will return "Lovely, Voluptuous", which can again be parsed.

2. Regarding the datatype, you can use any one you want. Integer is the
default and you can go with that. The database should have no problem
recognizing an int32.

3. >> Are there any classes in .NET that are specifically prepared to
I don't understand what you mean. What type of calculations ?

Hope this information helps,

Regards,

Cerebrus.
 
D

dbuchanan

Cerebrus,

But it doesn't It returns "14"
Console.WriteLine([Enum].Parse(GetType(TypeOfGirlFriend), "12"))
'Will return "Lovely, Voluptuous", which can again be parsed.

But it doesn't. It returns "12"

I was refering to the code you gave me above to pull the text from the
number.

Perhaps you don't remember some nuance of the code and that is why I
don't get the same results you describe.

By the way - I had to alter the constuction of the enumeration a little
from your posted code. That's okay. I assumed it was from memory and
that was not a problem. - Then again maybe I did make some mistake.

Here is my code
\\
Public Enum TypeOfGirlFriend
None = 1
Beautiful = 2
Lovely = 4
Voluptuous = 8
End Enum

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim myGirl As TypeOfGirlFriend = 14
MsgBox(myGirl.ToString()) ' I can tell here that the last 3
items in my enum were chosen.
End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button2.Click
'Dim myGirl As TypeOfGirlFriend = 14
MsgBox(TypeOfGirlFriend.Parse(GetType(TypeOfGirlFriend),
"12").ToString)
End Sub
//

How can I get the behavior you describe?

dbuchanan
 
C

Cerebrus

Hi again, (Is it Dave Buchanan ?)

Firstly, are you using VS 2003 or VS 2005 ?

Actually I did not type the code from memory. I have tested the above
code. The only difference between your code and mine is a simple but
very important thing : The Flags() attribute !!! When you remove this
simple attribute, the result will be as you describe, but when you add
it, you will get the result I mentioned (Parsable members). Remember,
it is this attribute which makes this Enum "special"...

I think that in that alteration you removed the Flags() attribute. I
see that in my original post, I had missed out the beginning "<" of
that statement. I'm sorry for that, must've been while pasting it here.

Your Enum should look like :

<Flags()> Public Enum TypeOfGirlFriend
None = 1
Beautiful = 2
Lovely = 4
Voluptuous = 8
End Enum

One other point, I usually use :

[Enum].Parse(GetType(TypeOfGirlFriend), "12")
instead of :
TypeOfGirlFriend.Parse(GetType(TypeOfGirlFriend), "12")


Hope it works now,

Feel free to post any other questions you might have,

Regards,

Cerebrus.
 
D

dbuchanan

Cerebrus,

Another question couple of questions...

First;
Here is my code. It behaves as described. Thank you.
\\
<Flags()> Public Enum TypeOfGirlFriend
None = 1
Beautiful = 2
Lovely = 4
Voluptuous = 8
End Enum

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim myGirl As TypeOfGirlFriend = 14
MsgBox(myGirl.ToString())
End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button2.Click
MsgBox([Enum].Parse(GetType(TypeOfGirlFriend), "12").ToString)
End Sub
//

Question #1)
How do I get it to return "2, 4, 8" for [Button1] and "4, 8" for
[Button2] rather than the text values?

Question #2)
How do I parse the individual values from the total. IOW how do I see
if 8 is contained in 14.I have been trying to find answers to this in
help for over an hour. I need to check each item individually.

For example:
is 1 set
is 2 set
is 4 set
is 8 set

I plan to do this so that the form can display the checkbox checked or
unchecked.

Can you help me with this?

Thank you,
dbuchanan
 
C

Cerebrus

Hi,
Question #1)
How do I get it to return "2, 4, 8" for [Button1] and "4, 8" for
[Button2] rather than the text values?

Answer #1)
I don't think you can do this, or if it is possible, it would require
unnecessary code. After all, the whole point of using such an
enumeration is to be able to test values using common names. Remember
that the members Beautiful, Lovely and Voluptuous are just another way
of referring to values 2,4 and 8, since the former is more easily
remembered.

Answer #2)
I think you should instead try to see if the value "Voluptuous" is
contained within the myGirl variable.

This can be done by :
-------------------------------
If ((myGirl And TypeOfGirlFriend.Beautiful) =
TypeOfGirlFriend.Beautiful) Then
Console.WriteLine("My girl is Beautiful")
End If

So, instead of checking :
-----------------------------------
is 1 set
is 2 set
is 4 set
is 8 set

Check if :
--------------
Is None set ?
Is Beautiful set ?
Is Lovely set ?
Is Voluptuous set ?

Another way, that I already told you is simply to use the ToString()
method and get all the set members.
---------------------------------------------
Dim arrMembers() As String = myGirl.ToString().Split(New Char() {","c})
Dim eachMember As String
For Each eachMember In arrMembers
Console.WriteLine(eachMember)
Next
---------------------------------------------

After that you can proceed as normal...

Hope this helps,

Regards,

Cerebrus.
 
D

dbuchanan

Cerebrus,

Look what I must do to populate the checkboxes in my form;
\\
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button3.Click

Dim myGirl As TypeOfGirlFriend = 14
Dim arrMembers() As String = myGirl.ToString().Split(New Char()
{","c})
Dim eachMember As String

For Each eachMember In arrMembers
If eachMember = "Beautiful" Then CheckBox1.Checked = True
If eachMember = " Lovely" Then CheckBox2.Checked = True
If eachMember = " Voluptuous" Then CheckBox3.Checked = True
Next

End Sub
//

Notice that when the value of myGirlfriend = 14 that I must put a
leading space before " Lovely" and " Voluptuous". That is because of
the placement of the comma in the string "Beautiful, Lovely,
Voluptuous". The code above will only for certain myGirl values and
give incorrect values for others.

Is there another way to determine if one value is contained within the
bitfield like with a pattern or mask of some sort?

thank you,
dbuchanan
 
C

Cerebrus

Hi,

I think this post will solve all the problems finally ! ;-)

1. To test for a value by Common names (The method I prefer) :

Use the Trim() method... as in :
------------------------------------------------------
For Each eachMember In arrMembers
Dim TrimmedMember as String = eachMember.Trim() ' To trim the
spaces, if any.
If eachMember = "Beautiful" Then CheckBox1.Checked = True
If eachMember = "Lovely" Then CheckBox2.Checked = True
If eachMember = "Voluptuous" Then CheckBox3.Checked = True
Next
------------------------------------------------------

In any case, the second method should have worked. I believe that is
the recommended method. The second method was :
------------------------------------------------------
If ((myGirl And TypeOfGirlFriend.Beautiful) =
TypeOfGirlFriend.Beautiful) Then
Console.WriteLine("My girl is Beautiful")
End If
------------------------------------------------------

2. To test for a value by values :

Refer my statement above in which I said that it might be difficult to
do it this way. I was working on something else at that time, and got
it wrong. Even after having explained this to you, I forgot that in
actuality, it's the values that are added or subtracted. So do this :
----------------------------------------------
Dim arrValues() As Integer =
[Enum].GetValues(GetType(TypeOfGirlFriend))
Dim eachVal As Integer
For Each eachVal In arrValues
If (eachVal And TypeOfGirlFriend.Beautiful = eachVal) Then
CheckBox1.Checked = True
If (eachVal And TypeOfGirlFriend.Lovely = eachVal) Then
CheckBox2.Checked = True
If (eachVal And TypeOfGirlFriend.Voluptuous = eachVal) Then
CheckBox3.Checked = True
Next
 
D

dbuchanan

Cerebrus,

I'm happy to get it down to this small amount of code.
\\
Dim myGirl As TypeOfGirlFriend = CType(Me.TextBox1.Text,
TypeOfGirlFriend)
Me.chkBeautiful.Checked = ((myGirl And
TypeOfGirlFriend.Beautiful) <> 0)
Me.chkLovely.Checked = ((myGirl And TypeOfGirlFriend.Lovely) <>
0)
Me.chkVoluptuous.Checked = ((myGirl And
TypeOfGirlFriend.Voluptuous) <> 0)
//

I could not figure out how you were using the array - where the value
was coming from? I would like to do some exploring with that.

Thank you,
dbuchanan
 
C

Cerebrus

Hi again,

Your code is now pretty and concise too ! And I tested it with a sample
form with 3 checkboxes and a textbox to enter the value. It seems to
work in all cases.

So... what problem are you facing now ?

Maybe we should talk in real time ? Do you use any instant messenger ?
I have MSN and Yahoo IM.

Regards,

Cerebrus.
 
D

dbuchanan

Cerebrus,

Yes I am happy with my concise code, however seeing that you were using
an array in a way I didn't understand got me interested in an
alternative approach that might have other advantages to offer.

dbuchanan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top