Click here to Skip to main content
15,881,172 members
Articles / Desktop Programming / WPF
Tip/Trick

A WPF CheckBox ListBox

Rate me:
Please Sign up or sign in to vote.
5.00/5 (13 votes)
11 Oct 2017CPOL 52.7K   2.5K   18   14
This tip presents a way to display checkboxes for selection of ListBox Items instead of the default highlighting

Introduction

Many people prefer to see checkboxes instead of the highlighting in a list box. There is a way to do this in XAML that does not require any change in ItemsSource, such as a property to bind to the IsChecked property of the Checkbox.

Design

The following is an example of the XAML that will replace the highlighting of ListBoxItem with a CheckBox:

        <ListBox Margin="15"
                 VerticalAlignment="Stretch"
                 ItemsSource="{Binding Items}"
                 SelectionMode="Multiple">
            <ListBox.Resources>
                <Style TargetType="ListBoxItem">
                    <Setter Property="OverridesDefaultStyle" Value="true" />
                    <Setter Property="SnapsToDevicePixels" Value="true" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="ListBoxItem">
                                <CheckBox Margin="5,2"
                                          IsChecked="{TemplateBinding IsSelected}">
                                    <ContentPresenter />
                                </CheckBox>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ListBox.Resources>
        </ListBox>

It requires the replacement of the ListBoxItem Template with a simple Template where the ContentPresenter is just contained in a CheckBox which has its IsChecked property bound to the ListBoxItem IsSelectedProperty. One of the things that this Template does is remove the Triggers that do the highlighting. Instead the highlighting depends on the Triggers for the CheckBox.

History

  • 10/11/2017: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Clifford Nelson Consulting
United States United States
Has been working as a C# developer on contract for the last several years, including 3 years at Microsoft. Previously worked with Visual Basic and Microsoft Access VBA, and have developed code for Word, Excel and Outlook. Started working with WPF in 2007 when part of the Microsoft WPF team. For the last eight years has been working primarily as a senior WPF/C# and Silverlight/C# developer. Currently working as WPF developer with BioNano Genomics in San Diego, CA redesigning their UI for their camera system. he can be reached at qck1@hotmail.com.

Comments and Discussions

 
QuestionTwo way binding is necessary Pin
sam-wheat 202217-Apr-22 5:30
sam-wheat 202217-Apr-22 5:30 
AnswerRe: Two way binding is necessary Pin
Clifford Nelson17-Apr-22 10:23
Clifford Nelson17-Apr-22 10:23 
AnswerRe: Two way binding is necessary Pin
Clifford Nelson24-May-22 8:55
Clifford Nelson24-May-22 8:55 
QuestionGet selection output with powershell Pin
Member 1478878331-Mar-20 15:43
Member 1478878331-Mar-20 15:43 
AnswerRe: Get selection output with powershell Pin
Member 1421197224-Jun-20 7:18
Member 1421197224-Jun-20 7:18 
QuestionGet selection output with powershell Pin
Member 1478878331-Mar-20 15:43
Member 1478878331-Mar-20 15:43 
Questionset selection for one ListBoxItem Pin
getfuture21-Mar-20 16:45
getfuture21-Mar-20 16:45 
QuestionHow to get the selected items which is checked ?? Pin
Member 1099173211-Sep-19 23:43
Member 1099173211-Sep-19 23:43 
AnswerRe: How to get the selected items which is checked ?? Pin
Member 1421197224-Jun-20 7:20
Member 1421197224-Jun-20 7:20 
BugDoes not update SelectedItems Pin
Member 17506285-Oct-18 6:13
Member 17506285-Oct-18 6:13 
QuestionThanks for the great article...but this code worked better for me Pin
Kevin Sherrill17-Apr-18 9:47
Kevin Sherrill17-Apr-18 9:47 
I found that by completely overriding the default style I lost my hover styling. Also, I found I now had to click on the checkbox itself or its associated text to select it. Clicking anywhere else on the ListItem "row" didn't work. I found that I preferred having the visible highlighted "rows", but when one was clicked it would simply check the CheckBox and not apply any other selection styling.

Since I'm working with Infragistics controls and themes. I grabbed a copy of their styling for the standard ListBoxItem style, commented out the storyboards for all the VisualState's in the "SelectionStates" VisualStateGroup, then wrapped a CheckBox control around the ContentPresenter.

If you're using the "vanilla" style that you can get from using the Blend trick (I open Blend with a new project, then add <listbox><listboxitem style="{StaticResource {x:Type ListBoxItem}}">, place the cursor on the ListBoxItem tag, then in your properties panel -> Miscellaneous -> Style, click the dot to the right, select "Convert to new resource". It will add the full style to your page, then you can modify it.) then you'll probably want to delete all the selection MultiTrigger's.

Then to use it I supplied a DisplayMemberPath to the ListBox like so to fill the content.
XML
<ListBox x:Name="OrgListBox"
         ItemContainerStyle="{StaticResource ListBoxItemCheckBoxStyle}"
         SelectionMode="Multiple"
         ScrollViewer.CanContentScroll="False"
         MinWidth="200"
         DisplayMemberPath="KeyValue"
         ItemsSource="{Binding Path=SearchCriteriaOrganizations, Mode=OneWay}">
</ListBox>

The style I used was huge with all the visual states so I've stripped some out.
The main point is wrapping the ContentPresenter in the CheckBox control:
XML
<Style x:Key="ListBoxItemCheckBoxStyle" TargetType="ListBoxItem">
  <Setter Property="Background" Value="{StaticResource ListBoxItemBackgroundBrush}"/>
  <Setter Property="BorderBrush" Value="{StaticResource ListBoxItemBorderBrush}"/>
  <Setter Property="Foreground" Value="{StaticResource ForegroundBrush}"/>
  <Setter Property="Padding" Value="5,2"/>
  <Setter Property="Margin" Value="0"/>
  <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
  <Setter Property="VerticalContentAlignment" Value="Stretch"/>
  <Setter Property="BorderThickness" Value="1"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="ListBoxItem">
        <Grid igPrim:XamlHelper.SnapsToDevicePixels="True">
          <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
              <!-- removed for brevity -->
            </VisualStateGroup>
            <VisualStateGroup x:Name="SelectionStates">
              <!-- removed for brevity -->
            </VisualStateGroup>
            <VisualStateGroup x:Name="FocusStates">
              <!-- removed for brevity -->
            </VisualStateGroup>
          </VisualStateManager.VisualStateGroups>
          <Border x:Name="BaseShape" Background="{TemplateBinding Background}"
                  BorderBrush="{TemplateBinding BorderBrush}"
                  BorderThickness="{TemplateBinding BorderThickness}">
            <Rectangle x:Name="Highlight"
                       Stroke="{StaticResource ListBoxItemHoverHighlightBorderBrush}"
                       StrokeThickness="1" Visibility="Collapsed"/>
          </Border>
          <Rectangle x:Name="SelectedBorder"
                     Fill="{StaticResource ListBoxItemSelectedBackgroundBrush}"
                     Stroke="{StaticResource ListBoxItemSelectedBorderBrush}"
                     Visibility="Collapsed"/>
          <CheckBox Margin="{TemplateBinding Padding}"
                    IsChecked="{TemplateBinding IsSelected}">
             <ContentPresenter x:Name="contentPresenter" Margin="0"
                    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
          </CheckBox>
          <Rectangle x:Name="FocusedVisualElement" IsHitTestVisible="False"
                     Visibility="Collapsed"
                     Stroke="{StaticResource ListBoxItemFocusedBorderBrush}"
                     StrokeThickness="1"/>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>


(Warning: I've not tested this extensively, but it seems to work well for me. Enjoy!)
QuestionContentProvider Pin
George Swan13-Oct-17 21:16
mveGeorge Swan13-Oct-17 21:16 
AnswerRe: ContentProvider Pin
Clifford Nelson16-Oct-17 2:51
Clifford Nelson16-Oct-17 2:51 
GeneralRe: ContentProvider Pin
George Swan16-Oct-17 4:49
mveGeorge Swan16-Oct-17 4:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.