Binding RadioButtons可从ListBox中显示的集合中选择一项
本文关键字:一项 选择 可从 RadioButtons ListBox 显示 Binding 集合 | 更新日期: 2023-09-27 17:57:33
我的模型中有一个ObservableCollection
,显示在视图中的ListBox
中。每个ListBoxItem
都显示一个单选按钮,该按钮应允许用户选择其中一个项目。ViewModel的属性应通过保留对所选项的引用来记录此选择。
如何设置双向绑定来执行此操作?
IValueConverter
应该允许我将RadioButton.IsChecked
绑定到VM属性,其中发生单选按钮的实际项目作为参数或IMultiValueConverter
中的值传递给转换器。我可以这样做:
- 基于VM属性与单选按钮关联的项目的比较,为
Convert()
返回true
/false
- 如果为
IsChecked==true
,则返回该项;如果为ConvertBack()
,则返回Binding.DoNothing
但是,ValueConverter
参数不能绑定到,因为它们不是依赖属性(因此我不能绑定到要用作ValueConverter
参数的项),并且我不能使用MultiConverter,因为尽管Convert()
将接收两个感兴趣的值,但ConvertBack()
将只接收IsChecked
的值。
票据
- 内置的ListBox选择机制已用于其他目的
- 感兴趣的集合嵌套在另一个集合中,并显示在包含的ListBox中
- ListBox绑定到模型中的集合。出于显而易见的原因,我希望不要在Model集合中实现告诉VM如何在View中记录事件的事件
我设法解决了这个问题:
- 在
ItemsPanel
的资源节点上包括一个转换器,它封装每个ListBoxItem
(或树的重复部分中的其他地方),因此每个项有一个转换器实例 - 为每个转换器所连接的项目向转换器添加一个属性(在我的示例中为
Host
),并在创建每个ListBoxItem
时以某种方式初始化它 - 将
IsChecked
绑定到需要使用转换器填充的ViewModel
属性
*我尝试将Host
属性作为绑定到DataContext
的DP(它应该是ListBox
在转换器所在点绑定到的集合的一个成员),但我根本无法将其用于我的嵌套ListBoxes
。我求助于containing元素的Initialized
事件和一些代码隐藏(这确实允许Host
恢复为普通属性;DP是多余的,但对于绑定来说是必要的)。
DataTemplate
:
<StackPanel Initialized="StackPanel_Initialized">
<StackPanel.Resources>
<!-- ExlcusionRadioConverter.Host is initialised in code behind -->
<local:ExclusionRadioConverter x:Key="ExclusionRadio" />
</StackPanel.Resources>
<RadioButton
GroupName="Exclusion"
IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}, Mode=FindAncestor}, Converter={StaticResource ExclusionRadio}, Path=DataContext.ExclusionCriterion}" />
<Label Content="{Binding Description}" />
</StackPanel>
Panel
Initialized
事件(NB此答案最初在Loaded
事件处理程序中有此代码,但这导致了一些问题):
private void StackPanel_Initialized(object sender, EventArgs e)
{
StackPanel panel = (StackPanel)sender;
ExclusionRadioConverter converter = (ExclusionRadioConverter)panel.FindResource("ExclusionRadio");
converter.Host = panel.DataContext as OptionListMember;
}
转换器:
[ValueConversion(typeof(object), typeof(bool))]
public class ExclusionRadioConverter : IValueConverter
{
public OptionListMember Host { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ReferenceEquals(value, Host);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((bool)value) ? Host : Binding.DoNothing;
}
}