#366 – Binding a Calendar Control’s SelectedDate Property to a Nullable DateTime

The SelectedDate property of a Calendar control reflects the currently selected date, if the SelectionMode is SingleDate, or the first date selected if the mode is SingleRange or MultipleRange.

You can use data binding to bind the SelectedDate property to a variable of type DateTime? (nullable DateTime).

In the example below, we bind SelectedDate to the FavoriteDay property of our data context.

    <StackPanel>
        <Calendar SelectionMode="SingleDate" SelectedDate="{Binding FavoriteDay}"/>
        <Button Content="Test" Click="Button_Click" Width="80" Margin="20"/>
    </StackPanel>

In the code-behind, we define the FavoriteDay property and set the data context to the parent class that contains the property.

        public DateTime? FavoriteDay { get; set; }

        public MainWindow()
        {
            this.InitializeComponent();
            this.DataContext = this;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            string msg;

            if (FavoriteDay == null)
                msg = "I don't have a favorite day";
            else
                msg = string.Format("My favorite day is {0:D}", FavoriteDay);

            MessageBox.Show(msg);
        }

#365 – SelectedDate and SelectedDates Properties of Calendar Control

The SelectedDate property of a Calendar control is a nullable DateTime (System.DateTime?) that represents a single selected date.

The SelectedDates property is an instance of SelectedDatesCollection, which is an ObservableCollection that contains DateTime values.  It represents the set of currently selected dates.

If the SelectionMode is None, or if no date is currently selected:

  • SelectedDate is null
  • SelectedDates is an empty collection

If SelectionMode is SingleDate and a date is selected:

  • SelectedDate contains a single DateTime value
  • SelectedDates contains a single DateTime element in the collection

If SelectionMode is SingleRange or MultipleRange and at least one date is selected:

  • SelectedDate contains a single DateTime value, equivalent to the first element in the SelectedDates collection
  • SelectedDates contains a DateTime element for each date that is currently selected

#364 – Allowing a User to Select Multiple Dates in a Calendar Control

By default, the Calendar control allows a user to select a single date.  You can set the SelectionMode property to allow the user to select more than one date.

SelectionMode (CalendarSelectionMode enumeration) can have one of the following values:

  • None – user can’t select date
  • SingleDate – select a single date  (default)

  • SingleRange – select a contiguous range of dates

  • MultipleRange – select multiple ranges of dates

If the SelectionMode is SingleDate, the SelectedDate property (DateTime) will contain the selected date.

If the SelectionMode is SingleRange or MultipleRange, the SelectedDates property (ObservableCollection of DateTime) will contain all of the selected dates.  The SelectedDate property will contain a copy of the first date in the SelectedDates collection.

#363 – Calendar Control Basics

The Calendar control displays an image of a calendar and allows a user to select a date.  By default, the calendar shows a single month that includes the current date.

    <StackPanel HorizontalAlignment="Center" Margin="15">
        <Calendar Name="cal"/>
        <Label Content="{Binding ElementName=cal, Path=SelectedDate, StringFormat=d}"/>
    </StackPanel>

When the user selects a date on the calendar, the SelectedDate property indicates the day that was selected.

You can use the left and right arrow icons at the top of the control to navigate to the previous/next month.

The Calendar control can also display a single year, or a single decade.  To switch to the Year mode, click on the name of the month at the top of the control.

You can now navigate to the previous/next year using the arrows, or click on a specific month.

You can switch to Decade mode by clicking on the year at the top of the control.

#362 – Changing the Text on a ToggleButton When a User Clicks On It

It’s reasonable to want to change the text on a ToggleButton when a user clicks on it, so it shows the current state.  You can do this by using a property trigger, which fires when the IsChecked property of the ToggleButton changes.

    <StackPanel HorizontalAlignment="Center" Margin="15">
        <Label Content="Click to arm the electric fence that surrounds your cube:"/>
        <StackPanel>
            <ToggleButton HorizontalAlignment="Center" Margin="5" Padding="5" Width="80">
                <ToggleButton.Style>
                    <Style TargetType="{x:Type ToggleButton}">
                        <Setter Property="Content" Value="Disarmed"/>
                        <Style.Triggers>
                            <Trigger Property="IsChecked" Value="True">
                                <Setter Property="Content" Value="ARMED"/>
                                <Setter Property="Foreground" Value="Red"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </ToggleButton.Style>
            </ToggleButton>
        </StackPanel>
    </StackPanel>


#361 – Creating a ToggleButton Whose Content Is an Image

Because ToggleButton is a ContentControl, it can contain a single child element that can be any .NET object.  You typically set the ToggleButton’s content to a text string, which appears as a label on the button.  But you can also set the content to some other control.

In the example below, the content of each ToggleButton in a panel is set to an Image control.

    <StackPanel HorizontalAlignment="Center" Margin="15">
        <Label Content="Click on cartoon characters that you like:"/>
        <StackPanel>
            <ToggleButton HorizontalAlignment="Center" Margin="5" Padding="5">
                <Image Source="001-Bugs.jpg" Stretch="None"/>
            </ToggleButton>
            <ToggleButton HorizontalAlignment="Center" Margin="5" Padding="5">
                <Image Source="002-Underdog.jpg" Stretch="None"/>
            </ToggleButton>
            <ToggleButton HorizontalAlignment="Center" Margin="5" Padding="5">
                <Image Source="003-Betty.jpg" Stretch="None"/>
            </ToggleButton>
            <ToggleButton HorizontalAlignment="Center" Margin="5" Padding="5">
                <Image Source="004-Bart.jpg" Stretch="None"/>
            </ToggleButton>
        </StackPanel>
    </StackPanel>

#360 – Binding a ToggleButton’s IsChecked Property to a Boolean Variable

Instead of handling the Checked and Unchecked events of a ToggleButton and then setting a boolean variable to represent the current state, you’ll most often just use data binding to bind the IsChecked property to a boolean variable.

In the example below, we have three ToggleButton controls, each bound to a boolean property.

        <StackPanel Orientation="Horizontal">
            <ToggleButton Content="Bold" IsChecked="{Binding Bold}"  FontWeight="Bold" Padding="5" />
            <ToggleButton Content="Italic" IsChecked="{Binding Italic}" FontStyle="Italic" Padding="5"/>
            <ToggleButton IsChecked="{Binding Underline}" Padding="5" >
                <TextBlock>
                    <Underline>Underline</Underline>
                </TextBlock>
            </ToggleButton>
        </StackPanel>
        <Button Content="Test" Click="Button_Click" Margin="15" Padding="3"/>

In the code-behind, we define the boolean properties that we can bind to and then set the data context to refer to the parent class.

        public bool Bold { get; set; }
        public bool Italic { get; set; }
        public bool Underline { get; set; }

		public MainWindow()
		{
			this.InitializeComponent();
            this.DataContext = this;
        }

        private void Test_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show(string.Format("Bold: {0}, Italic: {1}, Underline: {2}", Bold, Italic, Underline));
        }

#359 – ToggleButton Basics

The ToggleButton control is similar to the CheckBox control, in that allows the user to toggle something on/off in an application.  Instead of looking like a checkmark next to a label, however, the ToggleButton looks like a normal button.  The button appears to stay pressed in after you click it.  When you click the ToggleButton a second time, it appears to pop back out.

You specify the text that appears on the face of the ToggleButton using the Content property.

        <StackPanel Orientation="Horizontal">
            <ToggleButton Content="Bold" FontWeight="Bold" Padding="5"/>
            <ToggleButton Content="Italic" FontStyle="Italic" Padding="5"/>
            <ToggleButton Padding="5" >
                <TextBlock>
                    <Underline>Underline</Underline>
                </TextBlock>
            </ToggleButton>
        </StackPanel>

Like the CheckBox control, the IsChecked property indicates whether the ToggleButton is currently checked.

Also like the CheckBox control, the Checked and Unchecked events fire when the ToggleButton is checked or unchecked.

#358 – Binding a RadioButton to an Enumerated Type

You can bind RadioButton controls to an enum by using a value converter.

The XAML:

    <Window.Resources>
        <loc:EnumToBooleanConverter x:Key="enumToBooleanConverter" />
    </Window.Resources>

    <StackPanel HorizontalAlignment="Center" Margin="15">
        <Label Content="Favorite animated character?"/>
        <RadioButton IsChecked="{Binding Path=FavCharacter, Converter={StaticResource enumToBooleanConverter}, ConverterParameter={x:Static loc:CartoonCharacters.Gumby}}"
                     Content="Gumby"/>
        <RadioButton IsChecked="{Binding Path=FavCharacter, Converter={StaticResource enumToBooleanConverter}, ConverterParameter={x:Static loc:CartoonCharacters.PinkPanther}}"
                     Content="Pink Panther"/>
        <RadioButton IsChecked="{Binding Path=FavCharacter, Converter={StaticResource enumToBooleanConverter}, ConverterParameter={x:Static loc:CartoonCharacters.Magoo}}"
                     Content="Mr. Magoo"/>
    </StackPanel>

The enumeration:

    public enum CartoonCharacters
    {
        Gumby,
        PinkPanther,
        Magoo
    }

The enum-based property you’re binding to:

        public CartoonCharacters FavCharacter { get; set; }

And the value converter referenced by the XAML:

    public class EnumToBooleanConverter : IValueConverter
    {
        // Convert enum [value] to boolean, true if matches [param]
        public object Convert(object value, Type targetType, object param, CultureInfo culture)
        {
            return value.Equals(param);
        }

        // Convert boolean to enum, returning [param] if true
        public object ConvertBack(object value, Type targetType, object param, CultureInfo culture)
        {
            return (bool)value ? param : Binding.DoNothing;
        }
    }

#357 – RadioButton is a ContentControl

Because the RadioButton control is a ContentControl, it can contain a single child element that can be any .NET object.  When you specify a value for the Content property in XAML, you specify a text string that is used as the radio button’s label.  But you can also set the content to some other control.

In the example below, we set each RadioButton‘s content to a StackPanel containing an Image and a Label.  The user can still select just one item at a time from the group.

        <StackPanel HorizontalAlignment="Center" Margin="15">
            <Label Content="Who is your favorite animated character?"/>
            <RadioButton>
                <StackPanel>
                    <Image Source="001-Bugs.jpg" Stretch="None"/>
                    <Label Content="Bugs Bunny"/>
                </StackPanel>
            </RadioButton>
            <RadioButton>
                <StackPanel>
                    <Image Source="002-Underdog.jpg" Stretch="None"/>
                    <Label Content="Underdog"/>
                </StackPanel>
            </RadioButton>
            <RadioButton>
                <StackPanel>
                    <Image Source="003-Betty.jpg" Stretch="None"/>
                    <Label Content="Betty Boop"/>
                </StackPanel>
            </RadioButton>
            <RadioButton>
                <StackPanel>
                    <Image Source="004-Bart.jpg" Stretch="None"/>
                    <Label Content="Bart Simpson"/>
                </StackPanel>
            </RadioButton>
        </StackPanel>