Sco*_* O. 18 wpf databound radio-button
我有一个数据对象的选项列表,我想使用一个单选按钮列表,以允许用户选择一个,只有一个.功能类似于数据绑定组合框,但采用单选按钮格式.
愚蠢的我,我以为这将是内置的,但没有.你怎么做呢?
Sco*_* O. 30
基本上,在查看谷歌搜索结果之后,我开始使用MSDN讨论主题中的信息,其中WPF博士提供了一个答案,其中讨论了将ListBox设置为正确的样式.然而,当列表框被禁用时,背景是一个讨厌的颜色,我无法得到我的生活摆脱,直到我读列表框控件模板的MSDN例子,这表明了踢我的后台秘密Border元素屁股.
所以,这里的最终答案是这种风格:
<Style x:Key="RadioButtonList" TargetType="{x:Type ListBox}">
<!-- ControlTemplate taken from MSDN http://msdn.microsoft.com/en-us/library/ms754242.aspx -->
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
<Setter Property="MinWidth" Value="120"/>
<Setter Property="MinHeight" Value="95"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<Border Name="Border" Background="Transparent"
BorderBrush="Transparent"
BorderThickness="0"
CornerRadius="2">
<ScrollViewer Margin="0" Focusable="false">
<StackPanel Margin="2" IsItemsHost="True" />
</ScrollViewer>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="Border" Property="Background"
Value="Transparent" />
<Setter TargetName="Border" Property="BorderBrush"
Value="Transparent" />
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<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}">
<Border Name="theBorder" Background="Transparent">
<RadioButton Focusable="False" IsHitTestVisible="False"
IsChecked="{TemplateBinding IsSelected}">
<ContentPresenter />
</RadioButton>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
</Style>
Run Code Online (Sandbox Code Playgroud)
它为ListBox和Items提供了ControlTemplate和样式.它被这样使用:
<ListBox Grid.Column="1" Grid.Row="0" x:Name="TurnChargeBasedOnSelector" Background="Transparent"
IsEnabled="{Binding Path=IsEditing}"
Style="{StaticResource RadioButtonList}"
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:MainForm}}, Path=DataContext.RampTurnsBasedOnList}"
DisplayMemberPath="Description" SelectedValuePath="RampTurnsBasedOnID"
SelectedValue="{Binding Path=RampTurnsBasedOnID, NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}"/>
Run Code Online (Sandbox Code Playgroud)
我花在WPF上的时间越多,我就越认为它使得琐碎的疯狂困难和疯狂的琐事.请享用.斯科特
小智 15
将列表框绑定到ListBox的ItemsSource,其中包含具有属性Name的对象列表(这可以更改)
<ListBox Name="RadioButtonList">
<ListBox.ItemTemplate >
<DataTemplate >
<RadioButton GroupName="radioList" Tag="{Binding}" Content="{Binding Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Run Code Online (Sandbox Code Playgroud)
重要的GroupName ="radioList"
小智 8
超级简单,MVVM友好,利用DataTemplates进行类型化.XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate DataType="{x:Type local:Option}">
<RadioButton Focusable="False"
IsHitTestVisible="False"
Content="{Binding Display}"
IsChecked="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem}}">
</RadioButton>
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding Options}" SelectedItem="{Binding SelectedOption}"/>
</Grid>
Run Code Online (Sandbox Code Playgroud)
查看模型等:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new Vm();
}
}
public class Vm
{
public Option[] Options { get { return new Option[] {
new Option() { Display = "A" },
new Option() { Display = "B" },
new Option() { Display = "C" } }; } }
public Option SelectedOption { get; set; }
}
public class Option
{
public string Display { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
如果将选项包装到特定类型(或者可能已经存在).您只需为该类型设置DataTemplate,WPF将自动使用它.(在ListBox资源中定义DataTemplate以限制将应用DataTemplate的范围).
如果需要,还可以在DataTemplate中使用组名来设置组.
这比更改控件模板简单得多,但它确实意味着您在所选项目上获得蓝线.(再一次,没有一点造型无法修复).
当你知道如何时,WPF很简单.
我通过将a ValueConverter转换enum为a来完成此操作bool.通过传递单选按钮表示的枚举值,ConverterParameter转换器将返回是否应检查此单选按钮.
<Window.Resources>
<Converters:EnumConverter x:Key="EnumConverter" />
</Window.Resources>
<RadioButton IsChecked="{Binding Path=MyEnum, Mode=TwoWay,
Converter={StaticResource EnumConverter},
ConverterParameter=Enum1}"}
Content="Enum 1" />
<RadioButton IsChecked="{Binding Path=MyEnum, Mode=TwoWay,
Converter={StaticResource EnumConverter},
ConverterParameter=Enum2}"}
Content="Enum 2" />
Run Code Online (Sandbox Code Playgroud)
EnumConverter 定义如下:
public class EnumConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (targetType.IsAssignableFrom(typeof(Boolean)) && targetType.IsAssignableFrom(typeof(String)))
throw new ArgumentException("EnumConverter can only convert to boolean or string.");
if (targetType == typeof(String))
return value.ToString();
return String.Compare(value.ToString(), (String)parameter, StringComparison.InvariantCultureIgnoreCase) == 0;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (targetType.IsAssignableFrom(typeof(Boolean)) && targetType.IsAssignableFrom(typeof(String)))
throw new ArgumentException("EnumConverter can only convert back value from a string or a boolean.");
if (!targetType.IsEnum)
throw new ArgumentException("EnumConverter can only convert value to an Enum Type.");
if (value.GetType() == typeof(String))
{
return Enum.Parse(targetType, (String)value, true);
}
//We have a boolean, as for binding to a checkbox. we use parameter
if ((Boolean)value)
return Enum.Parse(targetType, (String)parameter, true);
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,我没有数据绑定到枚举列表以生成单选按钮,我已经手动完成了它们.如果你想通过绑定填充单选按钮列表,我认为你需要将IsChecked绑定更改为绑定到MultiBinding当前值和无线电的枚举值的绑定,因为你不能使用绑定ConverterParameter.