Skip to content

How a Binary Enum Simplifies a Calendar Week Day Selector

In Xojo 2021R2 binary enumerations were introduced. These Enums must be declared in a module and are treated by the compiler as a class. Xojo documentation for Enums can be found at Enumeration – Xojo Documentation.

I’d like to show you how to create an Enum for Days of the Week and demonstrate the use of that by creating a custom segmented button control.

Open Xojo and create a new Desktop Project.  Insert a module and give it a name – I called mine Enumerations.

Next, add an enumeration.

Call this Enum DaysOfWeek and make it a binary enum.

Next, fill in the Declarations.

Next, I’m going to add a bunch of Constants to the module, one for each day of the week.  This will allow me to localise the control later.

Now I’ll add a convenience method called ToString that will extend the DaysOfWeek Enum.

The code in this method is:

Var SelectedDays() As String

Var d As DaysOfWeek

d = DaysOfWeek.Sunday
If Value.Contains(d) Then
  SelectedDays.Add(Day1)
End If

d = DaysOfWeek.Monday
If Value.Contains(d) Then
  SelectedDays.Add(Day2)
End If

d = DaysOfWeek.Tuesday
If Value.Contains(d) Then
  SelectedDays.Add(Day3)
End If

d = DaysOfWeek.Wednesday
If Value.Contains(d) Then
  SelectedDays.Add(Day4)
End If

d = DaysOfWeek.Thursday
If Value.Contains(d) Then
  SelectedDays.Add(Day5)
End If

d = DaysOfWeek.Friday
If Value.Contains(d) Then
  SelectedDays.Add(Day6)
End If

d = DaysOfWeek.Saturday
If Value.Contains(d) Then
  SelectedDays.Add(Day7)
End If

Return String.FromArray(SelectedDays, ", ")

You can see from this code that it is possible to include multiple days in this Enum.  The return string might be “Sunday, Monday, Friday” for example.

Create the DaysOfWeek Control by dragging a segmented button from the library to the navigator and naming it DaysOfWeekControl.

Then use the Inspector Behaviour option to customise the control.

Change the default width to 500 and the selection style to 1 for multiple

Unfortunately, we can’t edit the segments here as the control is a textfield, not a textarea and the edit button is missing.  But we can edit the source file (you need a license capable of saving the project in text format).  Save and close the project, and open the DaysOfWeekControl.xojo_code file in Notepad, search for “One” which will find the initial value of the control.

You can see each segment is separated with “\r” which the IDE translates to <CR>.  Replace “One\rTwo” with “#Day1\r#Day2\r#Day3\r#Day4\r#Day5\r#Day6\r#Day7” which will tell the compiler to use the localised Day constants created earlier. Save the code file and reopen the project.

Now we can continue customising the control first adding a computed property Value As DaysOfWeek. In the Get method add this code:

Var Result As DaysOfWeek = 0 ' The default value is set to create an instance of Result
For i As Integer = 0 To 6 ' Each Segment in the control
  If me.SegmentAt(i).Selected Then
    Var d As DaysOfWeek = 2 ^ i ' Converts the index (i) to the binary number that matches the value of the enum
    Result = Result Or d ' Adds the selected day to the enum
  End If
Next i

Return Result

You’ll notice the first line sets the value of Result to 0, this is important as otherwise the variable will be Nil – remember this is being rendered as a class by the compiler.

In the Set Method place this code:

For i As Integer = 0 To 6 ' Index of each segment
  Var d As DaysOfWeek = 2 ^ i ' Convert the index (i) to binary
  me.SegmentAt(i).Selected = value.Contains(d) ' Set the selected state of the button
Next i

RaiseEvent ValueChanged(value)

This will show the button as pressed or not depending on whether the day is included on the value.  Now add an event definition.

Which will raise when a button is pressed, which means we need to handle the pressed event of the control.

Sub Pressed(segmentIndex as integer) Handles Pressed
  #Pragma Unused segmentIndex

  RaiseEvent ValueChanged(Value)
 End Sub

Time to use the control. We want to place a copy of the control onto Window1; we can either drag the control from the Navigator or select it from the Library (it will show in the Project Controls section). I’m also going to add a label to the Window under the DaysofWeek control, name it SelectedDaysLabel and make it the same width as the control (500). This will be where we will show the result of the days selected.

Next, handle the ValueChanged event on the control:

Sub ValueChanged(Value As DaysOfWeek) Handles ValueChanged
  SelectedDaysLabel.Text = Value.ToString
End Sub

When we run the project and select some days, we’ll see something similar to the following.

Now to show the power of the binary enum I’m going to add another declaration to the Enumeration “WeekDays” with a value of 62

62 is the total of the values for Monday through Friday. Once we have this, we can add a button to the window and set its “Pressed” event handler to:

Sub Pressed() Handles Pressed
  DaysOfWeekControl1.Value = DaysOfWeek.Weekdays
End Sub

Pressing the button will result in:

Taking this further we can add the enum value to the DateTime class by adding another Extension method to the module as below.

Public Function DayOfWeekEnum(Extends Value As DateTime) As DaysOfWeek  

  Var Result As DaysOfWeek = 2 ^ (Value.DayOfWeek - 1)
  Return Result

End Function

We need to subtract 1 from the DayOfWeek property of the passed DateTime object as the days are 1 based not 0 as in the control. To demonstrate how this works I’m going to add a multiline label to the window called SelectedDatesLabel and set that to show which dates over the next week have been selected by updating the ValueChanged handler as below:

Sub ValueChanged(Value As DaysOfWeek) Handles ValueChanged

SelectedDaysLabel.Text = Value.ToString

SelectedDatesLabel.Text = ""

For i As Integer = 1 To 7 ' From tomorrow for a week
 Var dt As DateTime = DateTime.Now.AddInterval(0, 0, i)
 If Value.Contains(dt.DayOfWeekEnum) Then
  SelectedDatesLabel.Text = SelectedDatesLabel.Text + _
  dt.ToString(DateTime.FormatStyles.Short, DateTime.FormatStyles.None) _
  + EndOfLine
    End If
  Next i

End Sub

That’s it folks, hope you enjoyed this tutorial.

Wayne Golding has been a Xojo developer since 2005 and is a Xojo MVP. He operates the IT Company Axis Direct Ltd which primarily develops applications using Xojo that integrate with Xero www.xero.com. Wayne’s hobby is robotics where he uses Xojo to build applications for his Raspberry Pi, often implementing IoT for remote control.