David
David

Reputation: 4117

Add checkbox to ComboboxItem

I want to a one or two checkboxes in my combobox (like microsoft word) enter image description here.

I put my checkbox in a separate Combobox Item, and set them item disabled. (I dont want that a user can select this item). But the checkbox is always disabled. enter image description here

Is there another solution?

That's my code:

    <ComboBox Height="36">
        <ComboBoxItem Height="36">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="30"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Grid Grid.Column="1">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="16" />
                        <RowDefinition Height="16" />
                    </Grid.RowDefinitions>
                    <TextBlock Text="Item Title 1" Grid.Row="0" FontWeight="Bold" />
                    <TextBlock Text="Item Description 1" Grid.Row="1" FontStyle="Italic" />
                </Grid>
            </Grid>
        </ComboBoxItem>
        <ComboBoxItem Height="36">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="30"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Grid Grid.Column="1">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="16" />
                        <RowDefinition Height="16" />
                    </Grid.RowDefinitions>
                    <TextBlock Text="Item Title 2" Grid.Row="0" FontWeight="Bold" />
                    <TextBlock Text="Item Description 2" Grid.Row="1" FontStyle="Italic" />
                </Grid>
            </Grid>
        </ComboBoxItem>
        <ComboBoxItem Height="25" IsEnabled="False">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="30"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Grid Grid.Column="1">
                    <CheckBox IsChecked="false" HorizontalAlignment="Left" Width="16" Height="16" IsEnabled="True" />
                    <Label Margin="10 0 0 0" HorizontalAlignment="Left" Content="I'm a checkbox ;)" />
                </Grid>
            </Grid>
        </ComboBoxItem>
    </ComboBox>

Upvotes: 1

Views: 862

Answers (1)

John Bowen
John Bowen

Reputation: 24453

When you disable an element, you are disabling it as a container as well, therefore disabling all of its children too. If you want an item that is not disabled but also not selectable it should not be included in the list of items for the ComboBox. For your purposes it may be a better idea to use a Menu since that's what you're trying to duplicate, rather than trying to squeeze unintended functionality into a ComboBox.

Having said that, if you do stick with a ComboBox, to add an item outside of the list you can modify the Template for the ComboBox (use Blend to generate a copy for you):

<ComboBox Height="36">
    <ComboBox.Template>
        <ControlTemplate TargetType="{x:Type ComboBox}">
            <Grid x:Name="MainGrid" SnapsToDevicePixels="true">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0"/>
                </Grid.ColumnDefinitions>
                <Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom">
                    <Microsoft_Windows_Themes:SystemDropShadowChrome x:Name="Shdw" Color="Transparent" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=MainGrid}">
                        <Border x:Name="DropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}">
                            <ScrollViewer x:Name="DropDownScrollViewer">
                                <Grid RenderOptions.ClearTypeHint="Enabled">
                                    <Canvas HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
                                        <Rectangle x:Name="OpaqueRect" Fill="{Binding Background, ElementName=DropDownBorder}" Height="{Binding ActualHeight, ElementName=DropDownBorder}" Width="{Binding ActualWidth, ElementName=DropDownBorder}"/>
                                    </Canvas>
                                    <StackPanel>
                                        <ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                                        <CheckBox IsChecked="false" Content="I'm a checkbox ;)" Margin="10"/>
                                    </StackPanel>
                                </Grid>
                            </ScrollViewer>
                        </Border>
                    </Microsoft_Windows_Themes:SystemDropShadowChrome>
                </Popup>
                <ToggleButton BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" Grid.ColumnSpan="2" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ComboBoxReadonlyToggleButton}"/>
                <ContentPresenter ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" Content="{TemplateBinding SelectionBoxItem}" ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsHitTestVisible="false" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
            </Grid>
            <ControlTemplate.Triggers>
                <Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="true">
                    <Setter Property="Margin" TargetName="Shdw" Value="0,0,5,5"/>
                    <Setter Property="Color" TargetName="Shdw" Value="#71000000"/>
                </Trigger>
                <Trigger Property="HasItems" Value="false">
                    <Setter Property="Height" TargetName="DropDownBorder" Value="95"/>
                </Trigger>
                <Trigger Property="IsEnabled" Value="false">
                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                    <Setter Property="Background" Value="#FFF4F4F4"/>
                </Trigger>
                <Trigger Property="IsGrouping" Value="true">
                    <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                </Trigger>
                <Trigger Property="ScrollViewer.CanContentScroll" SourceName="DropDownScrollViewer" Value="false">
                    <Setter Property="Canvas.Top" TargetName="OpaqueRect" Value="{Binding VerticalOffset, ElementName=DropDownScrollViewer}"/>
                    <Setter Property="Canvas.Left" TargetName="OpaqueRect" Value="{Binding HorizontalOffset, ElementName=DropDownScrollViewer}"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </ComboBox.Template>
    <ComboBoxItem Height="36">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="30"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Grid Grid.Column="1">
                <Grid.RowDefinitions>
                    <RowDefinition Height="16" />
                    <RowDefinition Height="16" />
                </Grid.RowDefinitions>
                <TextBlock Text="Item Title 1" Grid.Row="0" FontWeight="Bold" />
                <TextBlock Text="Item Description 1" Grid.Row="1" FontStyle="Italic" />
            </Grid>
        </Grid>
    </ComboBoxItem>
    <ComboBoxItem Height="36">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="30"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Grid Grid.Column="1">
                <Grid.RowDefinitions>
                    <RowDefinition Height="16" />
                    <RowDefinition Height="16" />
                </Grid.RowDefinitions>
                <TextBlock Text="Item Title 2" Grid.Row="0" FontWeight="Bold" />
                <TextBlock Text="Item Description 2" Grid.Row="1" FontStyle="Italic" />
            </Grid>
        </Grid>
    </ComboBoxItem>
</ComboBox>

Here I kept the entire default template but added in an extra StackPanel around the ItemsPresenter and put the new CheckBox in there. If you don't copy with Blend, to try the above template you'll also need the following xmlns (and the PresentationFramework.Aero reference in your project):

xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"

and these resources:

<Window.Resources>
    <Geometry x:Key="DownArrowGeometry">M 0 0 L 3.5 4 L 7 0 Z</Geometry>
    <Style x:Key="ComboBoxReadonlyToggleButton" TargetType="{x:Type ToggleButton}">
        <Setter Property="OverridesDefaultStyle" Value="true"/>
        <Setter Property="IsTabStop" Value="false"/>
        <Setter Property="Focusable" Value="false"/>
        <Setter Property="ClickMode" Value="Press"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ToggleButton}">
                    <Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}" SnapsToDevicePixels="true">
                        <Grid HorizontalAlignment="Right" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}">
                            <Path x:Name="Arrow" Data="{StaticResource DownArrowGeometry}" Fill="Black" HorizontalAlignment="Center" Margin="3,1,0,0" VerticalAlignment="Center"/>
                        </Grid>
                    </Microsoft_Windows_Themes:ButtonChrome>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsChecked" Value="true">
                            <Setter Property="RenderPressed" TargetName="Chrome" Value="true"/>
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Fill" TargetName="Arrow" Value="#AFAFAF"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

Upvotes: 1

Related Questions