Looking for a WPF ComboBox with checkboxes
Asked Answered
B

4

37

My google skills fail me. Anyone heard of a control like that for WPF. I am trying to make it look like this (winforms screenshot).

Backdrop answered 13/5, 2009 at 17:12 Comment(0)
M
66

You can do this yourself by setting the DataTemplate of the combo box. This article shows you how - for a listbox, but the principle is the same.


Another article here is perhaps a better fit for what you are trying to do, simple set the first column of the item template to be a checkbox and bind it to a bool on your business object.

<ComboBox.ItemTemplate>
    <DataTemplate>
        <StackPanel Orientation="Horizontal">
            <CheckBox IsChecked="{Binding IsSelected}"
                       Width="20" />
            <TextBlock Text="{Binding DayOfWeek}"
                       Width="100" />
        </StackPanel>
    </DataTemplate>
</ComboBox.ItemTemplate>
Mazer answered 13/5, 2009 at 17:29 Comment(6)
What if you want to create a re-usable control and you don't want to add IsSelected to your business objects?Pinfeather
You could create a new custom control that inherits from Combobox and alter the control's template to replace the control that sits in the popup with a list including the checkboxes. Listen to the checkboxes Checked event in the control and maintain a list of checked items which you can expose through a property.Mazer
It should be <CheckBox IsChecked="{Binding IsSelected}" Width="20" />, shouldn't it?Clubfoot
Yep, should be IsChecked. Checked is an event.Charolettecharon
@Philippe, alimbada - Thanks. Corrected.Mazer
@MartinHarris all those links are brokenGissing
E
24

There is my combobox. I use Martin Harris code and code from this link Can a WPF ComboBox display alternative text when its selection is null?

<ComboBox Name="cbObjects" Grid.Column="1" Grid.Row="1" VerticalAlignment="Center" Margin="2,2,6,0" SelectionChanged="OnCbObjectsSelectionChanged" >
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <CheckBox IsChecked="{Binding IsSelected}" Width="20" VerticalAlignment="Center" Checked="OnCbObjectCheckBoxChecked" Unchecked="OnCbObjectCheckBoxChecked" />
                <TextBlock Text="{Binding ObjectData}" VerticalAlignment="Center" />
            </StackPanel>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>
<TextBlock IsHitTestVisible="False" Name="tbObjects" Text="Выберите объекты..." Grid.Column="1" Grid.Row="1" VerticalAlignment="Center" Margin="6,2,6,0" />

Small class for datasource:

public class SelectableObject <T> {
    public bool IsSelected { get; set; }
    public T ObjectData { get; set; }

    public SelectableObject(T objectData) {
        ObjectData = objectData;
    }

    public SelectableObject(T objectData, bool isSelected) {
        IsSelected = isSelected;
        ObjectData = objectData;
    }
}

And there is two handler - one for handling CheckBox clicked and one for forming Text for ComboBox.

private void OnCbObjectCheckBoxChecked(object sender, RoutedEventArgs e) {
    StringBuilder sb = new StringBuilder();
    foreach (SelectableObject<tblObject> cbObject in cbObjects.Items) 
    {
        if (cbObject.IsSelected)
            sb.AppendFormat("{0}, ", cbObject.ObjectData.Description);
    }
    tbObjects.Text = sb.ToString().Trim().TrimEnd(',');
}

private void OnCbObjectsSelectionChanged(object sender, SelectionChangedEventArgs e) {
    ComboBox comboBox = (ComboBox)sender;
    comboBox.SelectedItem = null;
}

For ComboBox.ItemsSource I use

ObservableCollection<SelectableObject<tblObject>> 

where tblObject is type of my object, a list of which I want to display in ComboBox.

I hope this code is useful to someone!

Exhibition answered 7/7, 2011 at 6:28 Comment(5)
I liked the idea of SelectableObject. +1!Incorporated
imho StackPanel and TextBlock in template are redundant, could just bind Content property of checkbox to ObjectData..Erewhile
This solution works remarkably well despite being a bit kludgey (it requires two different, stacked controls). The accepted answer only gets you started and is incomplete. Other solutions involve modifying the ComboBox's template or creating custom controls and are far more complex.Crepitate
Please Explain How to add value in ObservableCollection<SelectableObject<tblObject>> as generic .Uchida
If you're binding any property of your object then the binding expression must be {Binding ObjectData.PropertyName}Havildar
S
11

Give a try to CheckComboBox from Extended WPF Toolkit. The main advantage for me is having two lists for binding:

  • all items available for selection
  • just selected items

I find this approach more practical. In addition you can specify value and display members of the collections you're binding.

If you don't want to bring a bunch of other controls with CheckComboBox, you can get the source code of it, it's pretty straightforward (need to bring Selector class as well).

Scottie answered 5/3, 2015 at 5:44 Comment(0)
S
8

ComboBox with Checkboxes

<ComboBox Height="16" Width="15">
    <CheckBox Content="First Checkbox" />
    <CheckBox Content="Second Checkbox" />
    <CheckBox Content="Third Checkbox" />
    <TextBlock Text="Some Text" />
</ComboBox>

The provided answers surprisingly didn't work for me, I tried many variations and kept getting error messages about the checkbox not being part of combobox and the data context seemed to be broken.

In the end I didn't have to do anything involving data templates or any code behind and my bindings are working fine (not shown in example)

ComboBox with Checkboxes

I must say I'm happy with how easy this turned out to be after reading all the answers.

Seduce answered 15/5, 2022 at 15:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.