tags:

views:

980

answers:

2

Iv seen other questions very similar to this but somehow I still cant get it working. here is the scenario.

What I have I have a ListBox that displays a list of my view models. Each view model has a list of children that are displayed in another, nested list box. I am using a DataTemplate to achieve this.

What I Want I want the children items to have a RadioButton that is selected when the ListBoxItem is selected and when the ListBox has focus (the inner ListBox).

Currently, the IsSelected portion of the above is working great, however when I move from one view model to the other (i.e. the first ListBox loses focus) the radio button on the first ListBox remains selected.

Here is the code:

        <Style TargetType="{x:Type ListBox}">
        <Setter Property="ItemContainerStyle">
            <Setter.Value>
                <Style TargetType="{x:Type ListBoxItem}" >
                    <Setter Property="Margin" Value="2" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                                <RadioButton Focusable="False">
                                    <RadioButton.Style>
                                        <Style TargetType="{x:Type RadioButton}">
                                            <Style.Triggers>
                                                <DataTrigger Binding="{Binding Path=IsFocused, Mode=OneWay, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBox}}}" Value="False">
                                                    <Setter Property="IsChecked" Value="False"/>
                                                </DataTrigger>
                                            </Style.Triggers>
                                        </Style>
                                    </RadioButton.Style>
                                    <RadioButton.IsChecked>
                                        <Binding Path="IsSelected" Mode="TwoWay" RelativeSource="{RelativeSource TemplatedParent}" />
                                    </RadioButton.IsChecked>
                                    <ContentPresenter></ContentPresenter>
                                </RadioButton>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </Setter.Value>
        </Setter>
    </Style>

I have also tried multiBinding, but that wasnt working either. Any suggestions?

UPDATE Update to include my attempt at multibinding:

<ControlTemplate TargetType="{x:Type ListBoxItem}">
<RadioButton>
<RadioButton.IsChecked>
    <MultiBinding>
        <MultiBinding.Converter>
            <DataExportTool:AllTrueConverter/>
        </MultiBinding.Converter>
        <Binding Path="IsSelected" Mode="TwoWay" RelativeSource="{RelativeSource TemplatedParent}"/>
        <Binding Path="IsFocused" Mode="OneWay" RelativeSource="{RelativeSource TemplatedParent}"/>
    </MultiBinding>
</RadioButton.IsChecked>
<ContentPresenter/>
</RadioButton>
</ControlTemplate>

And the converter:

public class AllTrueConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        return values.Cast<bool>().All(x => x);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        return Enumerable.Repeat((bool)value, 2).Cast<object>().ToArray();
    }
}

The IsSelected part of this works great, i.e. only one item in the list has the radiobutton selected at any time. However, when the control looses focus the selected item's radio button is still selected (not what I want).

A: 

Use a MultiBinding instead of a regular Binding, you will also need an IMultiValueConverter here:

<RadioButton.IsChecked>
    <Binding Path="IsSelected" Mode="TwoWay" RelativeSource="{RelativeSource TemplatedParent}" />
</RadioButton.IsChecked>

I usually do the examples myself, but this link should give you a good idea in how to use them. If not, I'll do a simplistic example later.

Basically what you want to do is send both IsFocused and IsSelected Dependency Properties in the MultiBinding, then in the MultiValueConverter say something like

return (bool)value[0] && (bool)value[1];

Where value[0] is IsFocused and value[1] is IsSelected or vice versa.

Good luck!

Carlo
A: 

Here is the xaml that ended up working. Disabling the radio button seems to be the key here.

<ControlTemplate TargetType="{x:Type ListBoxItem}">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <RadioButton x:Name="rbIsSelected" IsChecked="False" IsEnabled="False" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="3"  />
        <ContentPresenter Grid.Column="1"/>
    </Grid>
    <ControlTemplate.Triggers>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="IsSelected" Value="True"/>
                <Condition Property="Selector.IsSelectionActive" Value="True"/>
            </MultiTrigger.Conditions>
            <Setter Property="IsChecked" TargetName="rbIsSelected" Value="True"/>
        </MultiTrigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

Looking at the default template helped alot.

Kelly