2013-05-22 5 views
1

Я пишу простую программу, используя MVVM Model на WPF. В основном, когда пользователь нажимает на переключатель в группе переключателей, он обновляет свойство в модели просмотра с новым номером учетной записи. Проблема в том, что когда я нажимаю другую кнопку, конвертер вызывается для новой кнопки IsChecked Binding, а затем после этого он запускает конвертер для предыдущей кнопки IsChecked binding (для потери статуса проверки).WPF Radio Button Fires Converter в странном порядке

Это вызывает проблему, так как новая кнопка обновляет значение свойства с правильным номером учетной записи, а затем, когда старая кнопка вызывает конвертер, она возвращается обратно к старому значению. Я взломал его для работы, добавив статическую переменную в класс, и если свойство IsChecked является ложным, просто верните значение в статической переменной. У кого-нибудь есть лучшее решение для короткой передачи звонка конвертера в поле, которое теряет статус проверки. Код ниже:

Преобразователь:

class RadioToAccountConverter : IValueConverter 
{ 
    static string myValue; //HACK TO MAKE IT WORK 
    object IValueConverter.Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     return parameter.ToString(); 
    } 

    object IValueConverter.ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 

     if ((bool)value) 
     { 
      myValue = parameter.ToString(); // Hack to make it work 
      return parameter.ToString(); 
     } 
     return myValue; // Hack to make it work 
    } 
} 

XAML:

   <RadioButton Foreground="HotPink" 
          Grid.Column="0" 
          Content="6087721" 
          Tag="6087721" 
          IsChecked="{Binding Account, Converter={StaticResource Radio2Value}, Mode=OneWayToSource, ConverterParameter=6087721}"> 
       </RadioButton> 

       <RadioButton Foreground="HotPink" 
          Grid.Column="1" 
          Content="BFSC120" 
          IsChecked="{Binding Account, Converter={StaticResource Radio2Value}, Mode=OneWayToSource, ConverterParameter='BFSC120'}"> 
       </RadioButton> 

       <RadioButton Foreground="HotPink" 
          Grid.Column="2" 
          Content="BFSC121" 
          IsChecked="{Binding Account, Converter={StaticResource Radio2Value}, Mode=OneWayToSource, ConverterParameter=BFSC121}"> 
       </RadioButton> 

       <RadioButton Foreground="HotPink" 
          Grid.Column="3" 
          Content="BFSC206" 
          IsChecked="{Binding Account, Converter={StaticResource Radio2Value}, Mode=OneWayToSource, ConverterParameter=BFSC206}"> 

       </RadioButton> 

недвижимости:

public const string AccountPropertyName = "Account"; 

    private string _account; 

    /// <summary> 
    /// Sets and gets the Account property. 
    /// Changes to that property's value raise the PropertyChanged event. 
    /// </summary> 
    public string Account 
    { 
     get 
     { 
      return _account; 
     } 

     set 
     { 
      if (_account == value) 
      { 
       return; 
      } 

      RaisePropertyChanging(AccountPropertyName); 
      _account = value; 
      RaisePropertyChanged(AccountPropertyName); 
     } 
    } 

Любая помощь очень ценится.

ответ

1

Если вы определяете GroupName на каждом RadioButton, WPF будет управлять состояниями IsChecked.

Вы можете связать состояние с помощью {Binding SomeProperty, Mode=OneWayToSource}, если вы хотите, чтобы ViewModel знал о состоянии.

Один из способов приблизиться к этому было бы связать IsChecked свойство каждого RadioButton на всей ViewModel, просто привязать его к чему-то вроде

IsChecked="{Binding WholeViewModel, Mode=OneWayToSource, Converter={StaticResource MyRadioButtonConverter}, ConverterParameter=SomethingReallyUnique}" 

... где общественная собственность WholeViewModel это свойство, которое делает return this; в геттере. Это позволит вам иметь доступ к ViewModel и достаточно информации для запроса ViewModel, чтобы проверить, нужно ли проверять радиообъект или нет. Но, только сделайте это, если GroupNameDependencyProperty не может каким-то образом дать вам то, что вы хотите.

Для обработки щелчка по кнопкам, чтобы фактически изменить состояние ViewModel, вы должны реализовать ICommand в своей модели ViewModel и привязать свойство Command для RadioButton к {Binding ClickedCommand} и определить CommandParameter с любой строкой вы хотите. Этот подход гарантирует одностороннее отношение к состоянию IsChecked, предотвращая то, что вы описываете, я думаю.

Я разработаю образец кода, если вы считаете, что хотите его использовать.

+0

Спасибо, что это сработало отлично. –

+0

Какая часть? Я хотел бы отредактировать этот ответ, чтобы отразить подход, который вы на самом деле приняли, и, возможно, взять остальное и занести его в другой ответ ... –

3

Основываясь на том, что я понимаю, вы хотите дать пользователям возможность выбирать из списка номеров учетных записей. Вы выбираете презентацию (представление) - это группа переключателей.

Если это так, ключевая часть: вы хотите дать пользователям возможность выбирать из списка номеров счетов. Это означает, что вы должны использовать элемент управления ListBox, так как пользователи должны выбрать один соответствующих значений. Теперь, поскольку вы хотите визуально использовать переключатели, вам просто нужно предоставить альтернативу ItemsSource.ItemContainerStyle.


XAML:

<ListBox ItemsSource="{Binding AccountNumbers, Mode=OneWay"> 
    <ListBox.ItemContainerStyle> 
    <Style TargetType="{x:Type ListBoxItem}"> 
     <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type ListBoxItem}"> 
      <RadioButton Content="{Binding}" IsChecked="{Binding IsSelected, RelativeSource={x:Static RelativeSource.TemplatedParent}}"/> 
      </ControlTemplate> 
     </Setter.Value> 
     </Setter> 
    </Style> 
    </ListBox.ItemContainerStyle> 
</ListBox> 

Обратите внимание, что вам нужно добавить еще одно свойство на вашем ViewModel (я назвал его AccountNumbers). Например:

public IReadOnlyCollection<string> AccountNumbers { ... } 

Конечно, базовая коллекция может быть наблюдаемым, если вам нужно, чтобы это было, но это действительно до вас.