-1

I am using this answer to style a ListBox as RadioButton in order to simplify my MVVM code by driving the selection of the checked radio button via an enum - rather than having a bunch of bools that I have to manually map back and forth to the enum.

This works really well when the ListBoxItem content is a simple line of text. The radio button aligns with the text and all is happy. But when I change the content to be a UserControl, the radio button for that choice gets rendered at the vertical mid-point of the UserControl rather than at the top (where I want it).

Here is some code and an image that better explains what I am trying to do (Note that a bunch of stuff has been left out for clarity):

The UserControl that I am inserting as content into one of the choices

<UserControl x:Class="TestCtl">
    <StackPanel Orientation="Vertical" >
        <Label Margin="-5,0,0,0" Content="Choice #2"/>
        <CheckBox Margin="10,0,0,5">Option 1</CheckBox>
        <CheckBox Margin="10,0,0,5">Option 2</CheckBox>
        <CheckBox Margin="10,0,0,0">Option 3</CheckBox>
    </StackPanel>
</UserControl>

The ListBox (with the aforementioned style defined elsewhere)

<StackPanel Orientation="Vertical">
    <ListBox SelectedValuePath="Tag" 
             Style="{StaticResource RadioButtonList}" 
             SelectedValue="{Binding Blah Blah"}>
        <ListBoxItem Tag="Choice1" Content="Choice #1" />
        <ListBoxItem Tag="Choice2">
            <ContentControl>
                <subf:TestCtl />
            </ContentControl>
        </ListBoxItem>
        <ListBoxItem Tag="Choice3" Content="Choice #3"/>
        <ListBoxItem Tag="Choice4" Content="Choice #4" /> 
    </ListBox>
    <ComboBox blah blah/>
</StackPanel>

What it looks like when rendered:

enter image description here

I have tried setting both the VerticalAlignment and VerticalContentAlignment as well as playing with Margin and Padding in every location I can think of in both my xaml code and the style that I linked to, but no matter what I set I can't get the radio button and user control to align at their tops.

Is there anyway to achieve what I want by modifying either the style I am using or my code? Or am I just flat out doing this wrong?

Peter M
  • 7,309
  • 3
  • 50
  • 91
  • Style a ListBox as a RadioButton? You should read this: https://stackoverflow.com/questions/37790017/wpf-mvvm-radiobutton-handle-binding-with-single-property – mm8 Aug 31 '17 at 12:45
  • @mm8 Funnily enough I actually saw that one for the first time today and previously I had googled MVVM Radio buttons multiple times. I may try that approach but I'm wondering if I will still encounter the same alignment issue. – Peter M Aug 31 '17 at 12:50

2 Answers2

1

In the RabioButtonList style change this:

 <Setter Property="ItemContainerStyle">
            <Setter.Value>
                <Style TargetType="{x:Type ListBoxItem}" >
                    <Setter Property="Margin" Value="5" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                                <Border BorderThickness="0" Background="Transparent">
                                    <!-- CHANGE THIS -->
                                    <StackPanel Orientation="Horizontal">
                                        <RadioButton 
                                        Focusable="False"
                                        IsHitTestVisible="False"
                                        IsChecked="{TemplateBinding IsSelected}"/>
                                        <ContentPresenter />
                                    </StackPanel>
                                     <!------------------>
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </Setter.Value>
        </Setter>

In the user control set the label Padding to 5,0,0,0 (Thanks to mm8)

 <StackPanel Orientation="Vertical" >
    <Label Margin="-5,0,0,0" Content="Choice #2" Padding="5,0,0,0"/>
    <CheckBox Margin="10,0,0,5">Option 1</CheckBox>
    <CheckBox Margin="10,0,0,5">Option 2</CheckBox>
    <CheckBox Margin="10,0,0,0">Option 3</CheckBox>
</StackPanel>
The One
  • 4,560
  • 5
  • 36
  • 52
  • This is very close, but it has aligned the tops of the radio buttons with the top of the textual labels. Rather than the middle of the textual labels. I'm guessing a negative margin on the `ContentPresenter` will fix this – Peter M Aug 31 '17 at 13:14
  • Yes, I'm close to fix this – The One Aug 31 '17 at 13:16
  • Well, the label "Choise #2" is inside the usercontrol, that's why you can't align to it, so at some point you'll have to put fixed margins, paddings etc or move the label out of the user control and put it in the style – The One Aug 31 '17 at 13:36
  • I believe that for the current solution Choice #2 has to be in the user control as you can only set the content once. But long term I think that multiline radio button may be a better choice. – Peter M Aug 31 '17 at 13:41
0

Set the Padding of the Label to 0:

<ListBoxItem Tag="Choice1" Content="Choice #1" />
<ListBoxItem Tag="Choice2">
    <UserControl>
        <StackPanel Orientation="Vertical" >
            <Label Content="Choice #2" Padding="0"/>
            <CheckBox Margin="10,0,0,5">Option 1</CheckBox>
            <CheckBox Margin="10,0,0,5">Option 2</CheckBox>
            <CheckBox Margin="10,0,0,0">Option 3</CheckBox>
        </StackPanel>
    </UserControl>
</ListBoxItem>
<ListBoxItem Tag="Choice3" Content="Choice #3"/>
<ListBoxItem Tag="Choice4" Content="Choice #4" />

This should fix the vertical alignment issue. But you shouldn't have to use a ListBox in the first place to be able to bind a RadioButton to a single source property:

WPF + MVVM + RadioButton : Handle binding with single property

mm8
  • 163,881
  • 10
  • 57
  • 88