我见过其他与此非常相似的问题,但不知怎的,我仍然无法让它发挥作用。这是场景。
我有什么
我有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
部分效果很好,即列表中只有一个项目随时都会选择单选按钮。但是,当控件失去焦点时,仍然会选择所选项目的单选按钮(不是我想要的)。
答案 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,反之亦然。
祝你好运!