Vertical alignment of WPF Checkbox content with respect to checkbox

10,251

First of all don't waste your time with VerticalAlignment or VerticalContentAlignment (or even ControlTemplate). They're not going to do what you want or might expect.

As described on MSDN a BulletDecorator (which is the control that CheckBox and RadioButton uses to render a radio/check button) will set the position of the icon automatically. You have no additional control over this:

A Bullet always aligns with the first line of text when the Child object is a text object. If the Child object is not a text object, the Bullet aligns to the center of the Child object.

Unless you change the control template (unnecessary) you'll only be able to position the radio/check icon at the top if the content is text.

So if you do something like this it won't look good because you won't be able to move the icon no matter how many VerticalAlignment properties you try to set.

<RadioButton>
    <StackPanel>
        <TextBlock Text="First line"/>
        <TextBlock Text="Something else"/>
    </StackPanel>
</RadioButton>

BUT fortunately you can put pretty much anything you want in a TextBlock using InlineUIContainer. The text (or content) in the first line will dictate the position of the icon automatically. If you want something underneath the first line that isn't text, just use <Linebreak/> and then <InlineUIContainer/>

Here's an example that has an oversized TextBox to show more clearly what's happening.

<RadioButton>

    <TextBlock VerticalAlignment="Top" TextWrapping="Wrap">

        <TextBlock Text="Products with &lt;" VerticalAlignment="Center" Margin="0,0,5,0"/>

        <InlineUIContainer BaselineAlignment="Center">
            <TextBox FontSize="30" Width="25" Text="10" Margin="0,0,5,0"/>          
        </InlineUIContainer>

        <TextBlock VerticalAlignment="Center" Margin="0,0,5,0">
            <Run Text="days" FontWeight="Bold"/>
            <Run Text="inventory" />
        </TextBlock>

        <LineBreak/>    

        <InlineUIContainer>
            <StackPanel>
                <CheckBox Content="Include unsold products" />
                <CheckBox Content="Include something else" />
            </StackPanel>
        </InlineUIContainer>

    </TextBlock>
</RadioButton>
Share:
10,251
Admin
Author by

Admin

Updated on June 07, 2022

Comments

  • Admin
    Admin almost 2 years

    I have a checkbox whose XAML markup is as follows:

    <CheckBox HorizontalContentAlignment="Stretch">
        <StackPanel Orientation="Vertical">
            <TextBox x:Name="editTextBox" 
                Text="{Binding Path=Caption, Mode=TwoWay}"
                TextWrapping="Wrap"
                Visibility="{Binding Path=IsBeingEdited, Converter={StaticResource booleanToVisibilityConverter}}" />
            <TextBlock x:Name="itemText"
                TextWrapping="Wrap"                        
                Text="{Binding Path=Caption}" 
                Visibility="{Binding Path=IsBeingEdited, Converter={StaticResource reverseBooleanToVisibilityConverter}}">
            </TextBlock>
        </StackPanel>
    </CheckBox>
    

    The idea is that I can switch between the TextBlock (display) and TextBox (edit). However, when running the application, the CheckBox visual (the checkable square) is vertically centered. I would like it to be aligned with the top of the TextBlock/TextBox instead.

    I've noticed that when I only include a TextBlock (so no StackPanel, no TextBox), the checkbox is in fact aligned with the top of the TextBlock, so I'm assuming I'm missing some setting on the StackPanel?

  • springy76
    springy76 almost 12 years
    Now clicking the content doesn't change the checkbox state anymore. Bad UI design.
  • springy76
    springy76 almost 12 years
    When I place this RadioButton inside any Panel or ContentControl and disable this control (or any parent of it): IsEnabled=False -- then the nested CheckBoxes "Include unsold products" and "Include something else" are still active and clickable. InlineUIContainer also has no HorizonalAlignment so cannot be stretched to use the full width.