将RadioButton IsChecked绑定到ListBoxItem IsSelected和ListBox IsFocused

时间:2009-08-28 19:58:29

标签: wpf focus

我见过其他与此非常相似的问题,但不知怎的,我仍然无法让它发挥作用。这是场景。

我有什么 我有ListBox显示我的视图模型列表。每个视图模型都有一个子列表,显示在另一个嵌套列表框中。我正在使用DataTemplate来实现此目标。

我想要的东西 我希望子项目在RadioButton被选中时以及ListBoxItem具有焦点(内部ListBox)时选择了ListBox

目前,上面的IsSelected部分效果很好,但是当我从一个视图模型移动到另一个视图模型时(即第一个ListBox失去焦点),第一个ListBox上的单选按钮仍然存在地选择。

以下是代码:

        <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>

我也试过MultiBinding,但那也没有用。有什么建议吗?

更新 更新以包含我在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>

转换器:

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();
    }
}

IsSelected部分效果很好,即列表中只有一个项目随时都会选择单选按钮。但是,当控件失去焦点时,仍然会选择所选项目的单选按钮(不是我想要的)。

2 个答案:

答案 0 :(得分:2)

这是最终工作的xaml。禁用单选按钮似乎是关键。

<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>

查看默认模板有很多帮助。

答案 1 :(得分:1)

使用MultiBinding而不是常规Binding,您还需要一个IMultiValueConverter:

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

我通常会自己做这些示例,但是this link应该会给你一个如何使用它们的好主意。如果没有,我稍后会做一个简单的例子。

基本上你要做的是在MultiBinding中发送IsFocused和IsSelected Dependency Properties,然后在MultiValueConverter中说出类似

的内容
return (bool)value[0] && (bool)value[1];

其中value [0]为IsFocused且值1为IsSelected,反之亦然。

祝你好运!