Gigi Labs

Please follow Gigi Labs for the latest articles. Programmer's Ranch no longer has its domain, so please update your bookmarks and links to programmersranch.blogspot.com.

Saturday, July 19, 2014

C# WPF: CheckBoxes

In the previous article, "C# WPF: Basic Login Form using a Grid", we have already taken a look at some simple WPF controls including the TextBlock, TextBox and PasswordBox, and Button. In this article we will take a look at another control: the CheckBox.

So the first thing we're going to do is create a new WPF application, and we're going to create a sort of small questionnaire that will ask the user certain questions about them.

Let's add our first CheckBox by replacing the default <Grid> with the following in XAML:

    <CheckBox Name="PlayedTennisField">Have you ever played tennis?</CheckBox>

You can see how the text we entered inside the <CheckBox> element is actually displayed next to the CheckBox itself:


You can achieve the same thing by instead setting the Content property:

    <CheckBox Name="PlayedTennisField"
        Content="Have you ever played tennis?" />

CheckBoxes and Buttons are examples of Content Controls: they have that Content property (equivalent to setting the element's inner text, as we have seen above) which can be used to set text describing the control.

Let's add another CheckBox underneath the one we have:

    <CheckBox Name="BrokenLawField"
        Content="Have you ever broken the law?" />

You'll notice that the program will now refuse to compile:


Visual Studio is complaining because we have two items within the <Window> element. In fact, <Window> is also a content control, and that means that we can only have one element directly inside it. However, we can have many different controls inside a window by placing them inside something that isn't a content control, as we did with the <Grid> in the previous article.

This time, however, we'll use a <StackPanel> instead. A <StackPanel> may contain many different controls, and will by default display them underneath each other as in a list. Let's use it as follows:

    <StackPanel>
        <CheckBox Name="PlayedTennisField"
            Content="Have you ever played tennis?" />
        <CheckBox Name="BrokenLawField"
            Content="Have you ever broken the law?" />
    </StackPanel>

By placing the <StackPanel> directly inside the <Window>, the <Window> has just one element as its content, but at the same time we're indirectly allowing it to contain several others:


WPF provides us with two separate events that we can use to take action when a checkbox is either checked or unchecked. Add an event handler for each to the first checkbox by beginning to type the word "Checked", then pressing TAB twice when intellisense comes up, and then do the same for "Unchecked". Your first CheckBox's XAML should now look something like this:

    <CheckBox Name="PlayedTennisField"
        Content="Have you ever played tennis?"
        Checked="PlayedTennisField_Checked"
        Unchecked="PlayedTennisField_Unchecked" />

Note that you can also set both events to use the same handler.

You will now find a couple of event handlers that have been generated for you in your codebehind file (MainWindow.xaml.cs). If you add some code inside them, you can then run the program and test that it is indeed being called when the checkbox's state changes:


CheckBoxes are usually used for Boolean (true/false) data entry; however in some cases it may make sense to leave the value unset, in the sense that neither a true nor a false value is selected (i.e. a null value). In this case, the user may feel uncomfortable about telling the program whether they broke the law or not.

This situation is supported by using a ThreeState CheckBox. All we need to do is set the IsThreeState property of the second CheckBox to True. Clicking on the CheckBox will now cycle through checked, indeterminate (the shaded or unset state) and unchecked:


There is a separate event we can use to take action when the indeterminate state is set, and that is the Indeterminate event. You can now set up the second CheckBox as follows, and add whatever code you need in the three event handlers in the codebehind:

        <CheckBox Name="BrokenLawField"
            Content="Have you ever broken the law?"
            IsThreeState="True"
            Checked="BrokenLawField_Checked"
            Indeterminate="BrokenLawField_Indeterminate"
            Unchecked="BrokenLawField_Unchecked" />

Finally, let us see how we can extract the values from the checkboxes. To do this, let us first add a button beneath the checkboxes:

        <Button Name="SubmitButton"
            Content="Submit"
            Click="SubmitButton_Click" />

As we did in the previous article, you can access the controls from the codebehind by name. You'll find that the CheckBoxes have an IsChecked property, but it's a little awkward because it's not a regular bool, but a "bool?", which means "nullable boolean". In other words this can have values of not just true and false, but also null. It should be clear at this stage that this null value is there to support the indeterminate state.

So let's add some code to retrieve the state of the CheckBoxes and display a summary of the options that were selected:

        private void SubmitButton_Click(object sender, RoutedEventArgs e)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("Played tennis: ");
            sb.Append(NullableBooleanToString(this.PlayedTennisField.IsChecked));
            sb.Append(Environment.NewLine);

            sb.Append("Broke the law: ");
            sb.Append(NullableBooleanToString(this.BrokenLawField.IsChecked));

            MessageBox.Show(sb.ToString(), "Summary");
        }

        private string NullableBooleanToString(bool? value)
        {
            if (value == true)
                return "yes";
            else if (value == false)
                return "no";
            else
                return "unknown";
        }

And here is a test run:


Very good! In this article we have learned how to use the WPF CheckBox, including its events, threestate feature, and how to retrieve its state from the codebehind. We have also learned a little about content controls, and how to use a stack panel for to lay out controls in a vertical list.

Thanks for reading, and check back for more WPF tutorials! :)

No comments:

Post a Comment