Joh*_*an1 51 wpf binding radio-button
对于值1,2或3,将一组3个radiobuttons绑定到int类型属性的最简单方法是什么?
Joh*_*an1 85
我提出了一个简单的解决方案.
我有一个model.cs类:
private int _isSuccess;
public int IsSuccess { get { return _isSuccess; } set { _isSuccess = value; } }
Run Code Online (Sandbox Code Playgroud)
我有Window1.xaml.cs文件,DataContext设置为model.cs.xaml包含radiobuttons:
<RadioButton IsChecked="{Binding Path=IsSuccess, Converter={StaticResource radioBoolToIntConverter}, ConverterParameter=1}" Content="one" />
<RadioButton IsChecked="{Binding Path=IsSuccess, Converter={StaticResource radioBoolToIntConverter}, ConverterParameter=2}" Content="two" />
<RadioButton IsChecked="{Binding Path=IsSuccess, Converter={StaticResource radioBoolToIntConverter}, ConverterParameter=3}" Content="three" />
Run Code Online (Sandbox Code Playgroud)
这是我的转换器:
public class RadioBoolToIntConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int integer = (int)value;
if (integer==int.Parse(parameter.ToString()))
return true;
else
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return parameter;
}
}
Run Code Online (Sandbox Code Playgroud)
当然,在Window1的资源中:
<Window.Resources>
<local:RadioBoolToIntConverter x:Key="radioBoolToIntConverter" />
</Window.Resources>
Run Code Online (Sandbox Code Playgroud)
Mar*_*eIV 33
实际上,使用像这样的转换器打破了双向绑定,加上我上面所说的,你也不能使用枚举.更好的方法是使用针对ListBox的简单样式,如下所示:
注:相反的是DrWPF.com在他们的例子说明,也没有把里面单选按钮,否则如果添加与内容的项目,如按钮或别的东西,你将无法设定对焦或与其交互的ContentPresenter .这种技术解决了这个问题.此外,您需要处理文本的灰色以及删除标签上的边距,否则它将无法正确呈现.这种风格也适合你.
<Style x:Key="RadioButtonListItem" TargetType="{x:Type ListBoxItem}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<DockPanel LastChildFill="True" Background="{TemplateBinding Background}" HorizontalAlignment="Stretch" VerticalAlignment="Center" >
<RadioButton IsChecked="{TemplateBinding IsSelected}" Focusable="False" IsHitTestVisible="False" VerticalAlignment="Center" Margin="0,0,4,0" />
<ContentPresenter
Content = "{TemplateBinding ContentControl.Content}"
ContentTemplate = "{TemplateBinding ContentControl.ContentTemplate}"
ContentStringFormat = "{TemplateBinding ContentControl.ContentStringFormat}"
HorizontalAlignment = "{TemplateBinding Control.HorizontalContentAlignment}"
VerticalAlignment = "{TemplateBinding Control.VerticalContentAlignment}"
SnapsToDevicePixels = "{TemplateBinding UIElement.SnapsToDevicePixels}" />
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="RadioButtonList" TargetType="ListBox">
<Style.Resources>
<Style TargetType="Label">
<Setter Property="Padding" Value="0" />
</Style>
</Style.Resources>
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="ItemContainerStyle" Value="{StaticResource RadioButtonListItem}" />
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="TextBlock.Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="HorizontalRadioButtonList" BasedOn="{StaticResource RadioButtonList}" TargetType="ListBox">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel Background="Transparent" Orientation="Horizontal" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
Run Code Online (Sandbox Code Playgroud)
您现在拥有单选按钮的外观,但您可以进行双向绑定,并且可以使用枚举.这是如何做...
<ListBox Style="{StaticResource RadioButtonList}"
SelectedValue="{Binding SomeVal}"
SelectedValuePath="Tag">
<ListBoxItem Tag="{x:Static l:MyEnum.SomeOption}" >Some option</ListBoxItem>
<ListBoxItem Tag="{x:Static l:MyEnum.SomeOtherOption}">Some other option</ListBoxItem>
<ListBoxItem Tag="{x:Static l:MyEnum.YetAnother}" >Yet another option</ListBoxItem>
</ListBox>
Run Code Online (Sandbox Code Playgroud)
此外,由于我们明确地将传承ListBoxItem的样式分离出来而不是将其置于内联中,再次如其他示例所示,您现在可以创建一个新样式来自定义基于每个项目的内容,例如间距.(如果您只是尝试将ListBoxItem作为键控样式来覆盖通用控件目标,则此方法无效.)
这是一个在每个项目上下放置6的边距的示例.(注意你必须通过ItemContainerStyle属性显式应用样式,而不是简单地在ListBox的资源部分中定位ListBoxItem,原因如上所述.)
<Window.Resources>
<Style x:Key="SpacedRadioButtonListItem" TargetType="ListBoxItem" BasedOn="{StaticResource RadioButtonListItem}">
<Setter Property="Margin" Value="0,6" />
</Style>
</Window.Resources>
<ListBox Style="{StaticResource RadioButtonList}"
ItemContainerStyle="{StaticResource SpacedRadioButtonListItem}"
SelectedValue="{Binding SomeVal}"
SelectedValuePath="Tag">
<ListBoxItem Tag="{x:Static l:MyEnum.SomeOption}" >Some option</ListBoxItem>
<ListBoxItem Tag="{x:Static l:MyEnum.SomeOtherOption}">Some other option</ListBoxItem>
<ListBoxItem Tag="{x:Static l:MyEnum.YetAnother}" >Ter another option</ListBoxItem>
</ListBox>
Run Code Online (Sandbox Code Playgroud)
won*_*dra 28
我很惊讶没有人想出这种解决方案将它绑定到bool数组.它可能不是最干净的,但它可以很容易地使用:
private bool[] _modeArray = new bool[] { true, false, false};
public bool[] ModeArray
{
get { return _modeArray ; }
}
public int SelectedMode
{
get { return Array.IndexOf(_modeArray, true); }
}
Run Code Online (Sandbox Code Playgroud)
在XAML中:
<RadioButton GroupName="Mode" IsChecked="{Binding Path=ModeArray[0], Mode=TwoWay}"/>
<RadioButton GroupName="Mode" IsChecked="{Binding Path=ModeArray[1], Mode=TwoWay}"/>
<RadioButton GroupName="Mode" IsChecked="{Binding Path=ModeArray[2], Mode=TwoWay}"/>
Run Code Online (Sandbox Code Playgroud)
注意:如果您不想默认选中一个,则不需要双向绑定.TwoWay绑定是此解决方案的最大缺点.
优点:
Avi*_* P. 17
我知道这是过时的方式,但我有一个替代解决方案,它更轻,更简单.从中派生一个类System.Windows.Controls.RadioButton
并声明两个依赖属性RadioValue
和 RadioBinding
.然后在类代码中,覆盖OnChecked
并将RadioBinding
属性值设置为属性值的RadioValue
属性值.在另一个方向上,陷阱RadioBinding
使用回调更改为属性,如果新值等于RadioValue
属性的值,则将其IsChecked
属性设置为true
.
这是代码:
public class MyRadioButton : RadioButton
{
public object RadioValue
{
get { return (object)GetValue(RadioValueProperty); }
set { SetValue(RadioValueProperty, value); }
}
// Using a DependencyProperty as the backing store for RadioValue.
This enables animation, styling, binding, etc...
public static readonly DependencyProperty RadioValueProperty =
DependencyProperty.Register(
"RadioValue",
typeof(object),
typeof(MyRadioButton),
new UIPropertyMetadata(null));
public object RadioBinding
{
get { return (object)GetValue(RadioBindingProperty); }
set { SetValue(RadioBindingProperty, value); }
}
// Using a DependencyProperty as the backing store for RadioBinding.
This enables animation, styling, binding, etc...
public static readonly DependencyProperty RadioBindingProperty =
DependencyProperty.Register(
"RadioBinding",
typeof(object),
typeof(MyRadioButton),
new FrameworkPropertyMetadata(
null,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
OnRadioBindingChanged));
private static void OnRadioBindingChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
MyRadioButton rb = (MyRadioButton)d;
if (rb.RadioValue.Equals(e.NewValue))
rb.SetCurrentValue(RadioButton.IsCheckedProperty, true);
}
protected override void OnChecked(RoutedEventArgs e)
{
base.OnChecked(e);
SetCurrentValue(RadioBindingProperty, RadioValue);
}
}
Run Code Online (Sandbox Code Playgroud)
XAML用法:
<my:MyRadioButton GroupName="grp1" Content="Value 1"
RadioValue="val1" RadioBinding="{Binding SelectedValue}"/>
<my:MyRadioButton GroupName="grp1" Content="Value 2"
RadioValue="val2" RadioBinding="{Binding SelectedValue}"/>
<my:MyRadioButton GroupName="grp1" Content="Value 3"
RadioValue="val3" RadioBinding="{Binding SelectedValue}"/>
<my:MyRadioButton GroupName="grp1" Content="Value 4"
RadioValue="val4" RadioBinding="{Binding SelectedValue}"/>
Run Code Online (Sandbox Code Playgroud)
希望有人在这段时间后发现这个有用:)
我想出了使用Binding.DoNothing
转换器返回的解决方案,它不会破坏双向绑定。
public class EnumToCheckedConverter : IValueConverter
{
public Type Type { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null && value.GetType() == Type)
{
try
{
var parameterFlag = Enum.Parse(Type, parameter as string);
if (Equals(parameterFlag, value))
{
return true;
}
}
catch (ArgumentNullException)
{
return false;
}
catch (ArgumentException)
{
throw new NotSupportedException();
}
return false;
}
else if (value == null)
{
return false;
}
throw new NotSupportedException();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null && value is bool check)
{
if (check)
{
try
{
return Enum.Parse(Type, parameter as string);
}
catch(ArgumentNullException)
{
return Binding.DoNothing;
}
catch(ArgumentException)
{
return Binding.DoNothing;
}
}
return Binding.DoNothing;
}
throw new NotSupportedException();
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
<converters:EnumToCheckedConverter x:Key="SourceConverter" Type="{x:Type monitor:VariableValueSource}" />
Run Code Online (Sandbox Code Playgroud)
单选按钮绑定:
<RadioButton GroupName="ValueSource"
IsChecked="{Binding Source, Converter={StaticResource SourceConverter}, ConverterParameter=Function}">Function</RadioButton>
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
105845 次 |
最近记录: |