Databind radiobutton group to property

时间:2009-09-13 22:37:13

标签: wpf data-binding xaml

我有一个radiobutton小组:

<TextBlock Height="24" Text="Update Interval (min):"/>
<RadioButton x:Name="radioButtonTimerNone" IsChecked="{Binding UpdateInterval, Converter={StaticResource updateIntervalToCheckedConverter}, Mode=TwoWay}"} Content="None" />
<RadioButton x:Name="radioButtonTimerOne" IsChecked="{Binding UpdateInterval, Converter={StaticResource updateIntervalToCheckedConverter}, Mode=TwoWay}" 
                Content="1" />
<RadioButton x:Name="radioButtonTimerFive" IsChecked="{Binding UpdateInterval, Converter={StaticResource updateIntervalToCheckedConverter}, Mode=TwoWay}" 
                Content="5" />

和一个财产:

    public int UpdateInterval {
        get { return _updateInterval; }
        set { _updateInterval = value;
            onPropertyChanged("UpdateInterval");
        }
    }

如何将radiobuttons绑定到属性,因此当UpdateInterval为0时检查radioButtonTimerNone,当UpdateInterval为1时检查radioButtonTimerOne等。
我试图创建一个转换器,但它不能识别正在设置哪个rb:

[ValueConversion(typeof(RadioButton), typeof(bool))] 
class UpdateIntervalToCheckedConverter : System.Windows.Data.IValueConverter
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

我希望'value'是一个单选按钮,但它似乎是UpdateInterval的值。

感谢任何提示......

5 个答案:

答案 0 :(得分:2)

如果你正在使用MVVM并且绑定到ViewModel(我猜你是),我通常认为我的ViewModel是一个很大的ValueConverter。为什么不将这个逻辑放入每个属性?

以下是其中一个例子:

public bool Timer5Enabled
{
     get { return UpdateInterval == 5; }
}

然后你只需要绑定:

<RadioButton
    x:Name="radioButtonTimerOne"
    IsChecked="{Binding Timer5Enabled, Mode=OneWay}"
    Content="1" />

你唯一需要改变的就是绑定你的间隔更新逻辑来为你的依赖属性提高OnChanged:

public int UpdateInterval {
        get { return _updateInterval; }
        set { _updateInterval = value;
            onPropertyChanged("UpdateInterval");
            onPropertyChanged("Timer5Enabled");
            onPropertyChanged("...");
        }
    }

如果可以,可以避免使用ValueConverters。

答案 1 :(得分:1)

您的值转换器不会被告知哪个RadioButton更改了值 - 所有绑定都知道“IsChecked”属性已更改,因此IsChecked的新值是唯一可以告诉转换器的内容。

我想到的第一件事就是为每个绑定提供一个转换器参数:

<RadioButton 
    x:Name="radioButtonTimerNone" 
    IsChecked="{Binding UpdateInterval, Converter={StaticResource updateIntervalToCheckedConverter}, ConverterParameter=0, Mode=TwoWay}"
    Content="None" />
<RadioButton
    x:Name="radioButtonTimerOne"
    IsChecked="{Binding UpdateInterval, Converter={StaticResource updateIntervalToCheckedConverter}, ConverterParameter=1, Mode=TwoWay}"
    Content="1" />
<RadioButton 
    x:Name="radioButtonTimerFive"
    IsChecked="{Binding UpdateInterval, Converter={StaticResource updateIntervalToCheckedConverter}, ConverterParameter=5, Mode=TwoWay}"
    Content="5" />

所以现在“转换”方法中的“参数”参数将具有值“0”,“1”或“5”,具体取决于检查哪个RadioButton。我认为,虽然我不确定,参数将是字符串类型,因此您可能必须在询问值时考虑到这一点。

答案 2 :(得分:0)

您可能会考虑使用不同间隔的List<...>。列表类型最好是一些自定义类型(例如UpdateInterval)或KeyValuePair<K,V>,以将显示给用户的内容与实际值分开。

然后,您可以将ListBox绑定到此列表,并且每个ListBoxItem都会显示RadioButton。然后,在模板中,将单选按钮的IsChecked绑定到ListBoxItem.IsSelected

最后一步只是将您的媒体资源绑定到ListBox的{​​{1}}或SelectedItem

答案 3 :(得分:0)

这对我来说是个非常烦人的问题。

当您将多个RadioButtons分配给同一GroupName时,WPF RadioButton类有一个错误,该错误会删除IsChecked属性的绑定。人们已经做了很多工作,但当我不得不再次访问时,我想出了一个不会让我感到不安的人。

所以你需要做的就是用这个继承RadioButton类:

public class RadioButton: System.Windows.Controls.RadioButton
{
    protected override void OnClick()
    {
        base.OnClick();

        SetValue(CurrentValueProperty,CheckedValue);
    }

    public int CurrentValue
    {
        get { return (int)GetValue(CurrentValueProperty); }
        set { SetValue(CurrentValueProperty, value); }
    }

    // Using a DependencyProperty as the backing store for CurrentValue.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty CurrentValueProperty =
        DependencyProperty.Register("CurrentValue", typeof(int), typeof(RadioButton), new FrameworkPropertyMetadata(0,FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, CurrentValue_Changed));

    public static void CurrentValue_Changed(object sender, DependencyPropertyChangedEventArgs e)
    {
         ((RadioButton)sender).IsChecked = ((RadioButton)sender).CurrentValue == ((RadioButton)sender).CheckedValue;
    }

    public int CheckedValue
    {
        get { return (int)GetValue(CheckedValueProperty); }
        set { SetValue(CheckedValueProperty, value); }
    }

    // Using a DependencyProperty as the backing store for CheckedValue.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty CheckedValueProperty =
        DependencyProperty.Register("CheckedValue", typeof(int), typeof(RadioButton), new UIPropertyMetadata(0));
}

所有这一切都是添加两个依赖项属性,因此您可以进行相等比较。

所以在XAML中就是一个例子:

  <UserControl x:Class="MyClass"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:c="clr-namespace:MVVMLibrary;assembly=MVVMLibrary"
    Height="Auto" Width="Auto">

            <c:RadioButton CurrentValue="{Binding MyValue}" CheckedValue="1"  GroupName="SearchType" >Value 1</c:RadioButton>
            <c:RadioButton Grid.Column="1" CurrentValue="{Binding MyValue}" CheckedValue="2" GroupName="SearchType" >Value 2</c:RadioButton>
  </UserControl>

所以如果你注意到你所做的就是   1)绑定到CurrentValue属性   2)将CheckedValue属性设置为将检查RadioButton的值   3)将RadioButtons设置为相同的GroupName

如果您注意到我使用了CurrentValue和CheckedValue int类型。我这样做的原因是你实际上可以将CurrentValue绑定到枚举。我认为这很棒,但这只是我的意见,可能并不重要。 :)

希望这有助于某人。

答案 4 :(得分:0)

一种可能性是实现 IValueConverter 并配置它为您需要绑定的每个 RadioButton 传递预期的枚举值,正如我在我的here中所描述的那样博客。