Databind группа радиопереключателей к собственности - PullRequest
1 голос
/ 14 сентября 2009

У меня есть группа радиокнопок:

<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");
        }
    }

Как связать радиокнопки со свойством, так что radioButtonTimerNone проверяется, когда UpdateInterval равен 0, radioButtonTimerOne проверяется, когда UpdateInterval равен 1 и т. Д.
Я пытался создать конвертер, но он не определяет, какой 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 ]

2 голосов
/ 14 сентября 2009

Если вы используете 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 голос
/ 14 сентября 2009

Преобразователю значений не сообщается, какой 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" />

Таким образом, теперь параметр «parameter» в методе «Convert» будет иметь значение «0», «1» или «5» в зависимости от того, какой переключатель RadioButton был проверен. Я думаю , хотя я не уверен, что параметр будет иметь тип string, поэтому вам, возможно, придется принять это во внимание при запросе значения.

0 голосов
/ 23 июня 2010

Одна из возможностей - реализовать IValueConverter и настроить его, передавая ожидаемое значение перечисления для каждого RadioButton , который необходимо связать, как я описал здесь в моем блог.

0 голосов
/ 27 октября 2009

Это была очень неприятная проблема для меня.

В классе WPF RadioButton есть ошибка, которая удаляет привязку для свойства IsChecked при назначении нескольких RadioButton для одного и того же GroupName. Люди много обходились, но когда мне снова пришлось это посетить, я нашел такой, который не вызывает у меня тошноты.

Итак, вы должны создать подкласс класса 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 на то же имя группы

Если вы заметили, что я сделал intValue и CheckedValue типа int. Причина, по которой я это сделал, заключается в том, что вы можете связать CurrentValue с перечислением. Я думаю, что это круто, но это только мое мнение, которое, вероятно, не имеет большого значения. :)

Надеюсь, это кому-нибудь поможет.

0 голосов
/ 15 сентября 2009

Возможно, вы могли бы подумать о том, чтобы иметь List<...> с разными интервалами. Тип списка предпочтительно должен быть некоторого пользовательского типа (например, UpdateInterval) или KeyValuePair<K,V>, чтобы отделить то, что показано пользователю, от фактического значения.

Тогда вы можете иметь ListBox, привязанный к этому списку, и каждый ListBoxItem будет отображать шаблон RadioButton. Затем в шаблоне вы привязываете переключатель IsChecked к ListBoxItem.IsSelected.

Последний штрих - просто связать вашу собственность с ListBox SelectedItem или SelectedValue.

...