使用 ItemControl 和 DataBinding 时,RadioButton 分组在 WPF 中不起作用
RadioButton grouping not working in WPF when using ItemControl and DataBinding
我在使用 WPF 表单和 DataBinding 时遇到了 RadioButtons 分组的问题。
如果我手动创建我的控件,则行为符合预期,并且用户只能 select 单选按钮组(底部 GroupBox)中的一项,但如果我使用嵌套的 ItemControls 生成我的布局和使用数据绑定分组无法按预期工作,并且允许用户 select 一组(顶部 groupBox)中的多个单选按钮,如链接屏幕截图中所示 1.
我已尝试绑定 GroupName 属性,但未能以某种方式找到用于 GroupName 属性 的绑定 属性。
也许可以使用同一个网格行中TextBlock的Text 属性,但我找不到合适的Binding语法来引用它。
让分组起作用的方法是什么?
这里是 XAML:
<Window x:Class="RadioButtonMadness.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" Title="MainWindow" SizeToContent="WidthAndHeight">
<Window.Resources>
<Style TargetType="RadioButton">
<Setter Property="Margin" Value="10" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Height" Value="22" />
</Style>
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="10" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Height" Value="22" />
</Style>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions />
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<GroupBox Header="Prognostic factors - NOK">
<ItemsControl ItemsSource="{Binding PrognosticFactors}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Name="PrognosticFactors" Grid.Row="0" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions />
<TextBlock Text="{Binding Title}" />
<ItemsControl ItemsSource="{Binding Options}" Grid.Column="1">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton Content="{Binding Key}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</GroupBox>
<GroupBox Header="Prognostic factors - OK" Grid.Row="1">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions/>
<TextBlock Text="Test4" Grid.Column="0"/>
<StackPanel Orientation="Horizontal" Grid.Column="1">
<RadioButton Content="One"/>
<RadioButton Content="Two"/>
<RadioButton Content="Three"/>
</StackPanel>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions />
<TextBlock Text="Test5" Grid.Column="0"/>
<StackPanel Orientation="Horizontal" Grid.Column="1">
<RadioButton Content="One"/>
<RadioButton Content="Two"/>
<RadioButton Content="Three"/>
</StackPanel>
</Grid>
</StackPanel>
</GroupBox>
</Grid>
</Window>
以及后面的代码:
using System;
using System.Collections.Generic;
using System.Windows;
namespace RadioButtonMadness
{
public class Option
{
public String Key{ get; set; }
public Double Value { get; set; }
public Option(String key, Double value)
{
Key = key;
Value = value;
}
}
public class PrognosticFactor
{
private String title;
public List<Option> Options
{
get
{
var list = new List<Option>();
list.Add(new Option("One", 1));
list.Add(new Option("Two", 2));
list.Add(new Option("Three", 3));
return list;
}
}
public String Title
{
get { return title; }
}
public PrognosticFactor(String value)
{
title = value;
}
}
public class ViewModel
{
public List<PrognosticFactor> PrognosticFactors
{
get
{
var list = new List<PrognosticFactor>();
list.Add(new PrognosticFactor("Test1"));
list.Add(new PrognosticFactor("Test2"));
list.Add(new PrognosticFactor("Test3"));
return list;
}
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
}
}
只需将 GroupName 绑定到标题 属性。你可以这样做:
<ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton Content="{Binding Key}" GroupName="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Grid}, Path=DataContext.Title}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
我在使用 WPF 表单和 DataBinding 时遇到了 RadioButtons 分组的问题。
如果我手动创建我的控件,则行为符合预期,并且用户只能 select 单选按钮组(底部 GroupBox)中的一项,但如果我使用嵌套的 ItemControls 生成我的布局和使用数据绑定分组无法按预期工作,并且允许用户 select 一组(顶部 groupBox)中的多个单选按钮,如链接屏幕截图中所示 1.
我已尝试绑定 GroupName 属性,但未能以某种方式找到用于 GroupName 属性 的绑定 属性。 也许可以使用同一个网格行中TextBlock的Text 属性,但我找不到合适的Binding语法来引用它。
让分组起作用的方法是什么?
这里是 XAML:
<Window x:Class="RadioButtonMadness.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" Title="MainWindow" SizeToContent="WidthAndHeight">
<Window.Resources>
<Style TargetType="RadioButton">
<Setter Property="Margin" Value="10" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Height" Value="22" />
</Style>
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="10" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Height" Value="22" />
</Style>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions />
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<GroupBox Header="Prognostic factors - NOK">
<ItemsControl ItemsSource="{Binding PrognosticFactors}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Name="PrognosticFactors" Grid.Row="0" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions />
<TextBlock Text="{Binding Title}" />
<ItemsControl ItemsSource="{Binding Options}" Grid.Column="1">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton Content="{Binding Key}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</GroupBox>
<GroupBox Header="Prognostic factors - OK" Grid.Row="1">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions/>
<TextBlock Text="Test4" Grid.Column="0"/>
<StackPanel Orientation="Horizontal" Grid.Column="1">
<RadioButton Content="One"/>
<RadioButton Content="Two"/>
<RadioButton Content="Three"/>
</StackPanel>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions />
<TextBlock Text="Test5" Grid.Column="0"/>
<StackPanel Orientation="Horizontal" Grid.Column="1">
<RadioButton Content="One"/>
<RadioButton Content="Two"/>
<RadioButton Content="Three"/>
</StackPanel>
</Grid>
</StackPanel>
</GroupBox>
</Grid>
</Window>
以及后面的代码:
using System;
using System.Collections.Generic;
using System.Windows;
namespace RadioButtonMadness
{
public class Option
{
public String Key{ get; set; }
public Double Value { get; set; }
public Option(String key, Double value)
{
Key = key;
Value = value;
}
}
public class PrognosticFactor
{
private String title;
public List<Option> Options
{
get
{
var list = new List<Option>();
list.Add(new Option("One", 1));
list.Add(new Option("Two", 2));
list.Add(new Option("Three", 3));
return list;
}
}
public String Title
{
get { return title; }
}
public PrognosticFactor(String value)
{
title = value;
}
}
public class ViewModel
{
public List<PrognosticFactor> PrognosticFactors
{
get
{
var list = new List<PrognosticFactor>();
list.Add(new PrognosticFactor("Test1"));
list.Add(new PrognosticFactor("Test2"));
list.Add(new PrognosticFactor("Test3"));
return list;
}
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
}
}
只需将 GroupName 绑定到标题 属性。你可以这样做:
<ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton Content="{Binding Key}" GroupName="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Grid}, Path=DataContext.Title}" />
</DataTemplate>
</ItemsControl.ItemTemplate>