3

I am unable to bind two radiobuttons to my xaml form and IsChecked property with same group names for which I also used nullabletoboolconverters. however, the radiobuttons ischecked property does not get changed in my code(it is not at all hitting the breakpoint, once we hit the first radiobutton after second one) and I am binding ischecked properties of two of them seperately as I need to set the visibility of some other panel on the form based on the radiobuttons property.

the following is my xaml code and later is my viewmodel.cs code for radiobutton properties:

   <RadiobuttonSelectedConverter x:Key="CheckedSelection"/>// declaring my converter class in my resource dictionary.

  <StackPanel Orientation="Horizontal" Grid.Column="0" Grid.Row="3" Margin="10,5,0,0">
        <RadioButton GroupName="RadiosGroup" IsChecked="{Binding IsRadioButton1,Mode=TwoWay,
             Converter={StaticResource CheckedSelection}, ConverterParameter=true}">
                    First</RadioButton>
        <RadioButton GroupName="RadiosGroup" 
                     Margin="40,0,0,0" IsChecked="{Binding IsRadioButton2,Mode=TwoWay, 
            Converter={StaticResource CheckedSelection}, ConverterParameter=true}">Second</RadioButton>
    </StackPanel>



    private bool _isRadioButton1;

    public bool IsRadioButton1
    {
        get
        {
            return _isRadioButton1;
        }
        set
        {
            if _isRadioButton1!= value)
            {
                _isRadioButton1= value;

                IsRadioButton2= false;
                OnPropertyChanged("IsRadioButton1");

            }
        }
    }


    private bool _isRadioButton2;

    public bool IsRadioButton2
    {
        get
        {
            return _isRadioButton2;
        }
        set
        {
            if (_isRadioButton2 != value)
            {
                _isRadioButton2 = value;

              IsRadioButton1= false;
              OnPropertyChanged("IsRadioButton2");

            }
        }
    }

the following is my Converter code:

  [ValueConversion(typeof(bool?), typeof(bool))]
public class RadiobuttonSelectedConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        bool param = bool.Parse(parameter.ToString());
        if (value == null)
        {
            return false;
        }
        else
        {
            return !((bool)value ^ param);
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        bool param = bool.Parse(parameter.ToString());
        return !((bool)value ^ param);
    }
}

Someone please help me resolving my issue thanks in advance..

user1105705
  • 89
  • 1
  • 1
  • 10
  • 1
    Your converter looks strange. Why aren't you simply returning `value == param`? – Daniel Hilgarth Aug 27 '12 at 12:55
  • oh..thanks for that...Am actually using that from the link - "http://geekswithblogs.net/claraoscura/archive/2008/10/17/125901.aspx", as is....can you please let me know where exactly is it going wrong.... – user1105705 Aug 27 '12 at 13:00
  • @user1105705 Since your property is of type `bool`, which can't be `null`, why are you using a `Converter` in the first place? Does your code work correctly without the converter? – Rachel Aug 27 '12 at 13:21
  • yes, but then its firing the changed property only for once....I mean on selecting the radiobutton for the first time..not every time. – user1105705 Aug 27 '12 at 13:26

2 Answers2

6

Personally I wouldn't code associated RadioButtons like this at all. Since the selection behavior you want is the same used for a ListBox, I find it easiest to simply use a ListBox that is styled to use RadioButtons for each item.

The code-behind typically will contain

  • ObservableCollection<string> Options
  • string SelectedOption

and I will use this style for the ListBox:

<Style x:Key="RadioButtonListBoxStyle" TargetType="{x:Type ListBox}">
    <Setter Property="BorderBrush" Value="Transparent"/>
    <Setter Property="KeyboardNavigation.DirectionalNavigation" Value="Cycle" />
    <Setter Property="ItemContainerStyle">
        <Setter.Value>
            <Style TargetType="{x:Type ListBoxItem}" >
                <Setter Property="Margin" Value="2, 2, 2, 0" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <Border Background="Transparent">
                                <RadioButton
                                    Content="{TemplateBinding ContentPresenter.Content}" VerticalAlignment="Center"
                                    IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}"/>

                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Setter.Value>
    </Setter>
</Style>

The style is applied like this:

<ListBox ItemsSource="{Binding Options}"
         SelectedValue="{Binding SelectedOption}"
         Style="{StaticResource RadioButtonListBoxStyle}" />

You can also use something else instead of a String for the collection, such as a ChildViewModel, then set your related View based on the current item, which means you don't have to bother with the Visibility of the associated panel in your ViewModel either.

<DockPanel>
    <ListBox ItemsSource="{Binding OptionViewModels}"
             SelectedValue="{Binding SelectedViewModel}"
             Style="{StaticResource RadioButtonListBoxStyle}"
             DockPanel.Dock="Left">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding DisplayName}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

    <ContentControl Content="{Binding SelectedViewModel}" />
</DockPanel>

But as for your actual problem, I can think of 3 reasons it might be behaving incorrectly.

The first is outlined in Jay's answer: you are setting IsChecked2 to false in your setter for IsChecked1, and IsChecked2 sets IsChecked1 to false in its setter, so the end result is both values are false.

The second is it might be a problem with your converter. You said it a comment it was working correctly without the converter, so I think that may be part of the problem.

And last of all, I believe changing grouped RadioButtons will trigger an IsOptionA.IsSelected = false for the old item and an IsOptionB.IsSelected = true for the newly selected item, and its possible those two are getting crossed somewhere.

Community
  • 1
  • 1
Rachel
  • 130,264
  • 66
  • 304
  • 490
  • yah Thank you once again for your response....that has worked well...I have created an observablecollection to generate the radiobuttons and In myclass I have created a couple of properties for checking the Id and name for the selected radiobutton...so that I could go on working with my condition based on the radiobutton Id. However...creating a collection object for binding only two radiobuttons which I did now, seems to be somewhat unusual....Anyways that has somehow solved my issue for now....thank you. – user1105705 Aug 27 '12 at 16:36
  • @user1105705 It seemed weird to me too at first, but over time I got used to it and now can't imaging handling this kind of situation any other way. It makes it very easy to add onto later on, and I find the logic much easier to follow and maintain than trying to manipulate multiple bool values. Glad it worked out for you :) – Rachel Aug 27 '12 at 16:44
1

A couple of issues here.

  1. You don't need a converter. Make IsRadioButton1 and IsRadioButton2 properties of type bool?, and the TwoWay Binding will suffice, or just leave it as bool if tri-state is not applicable for you.
  2. The logic in your setters appears to be incorrect. In both cases, you are setting the value of the other RadioButton to false, so if IsRadioButton1 is true and you then set IsRadioButton2 to true, the setter will call IsRadioButton = false, and then that setter will call IsRadioButton2 = false. They will both end up being false.

You probably want this to read if(value) IsRadioButton2 = false;


edit

Actually, as I recall, RadioButton is not meant to be bound to a bool property the way a CheckBox is. I think you bind all of the RadioButtons to one property, and use a Converter with a ConverterParameter to set the property. I'll find an example and post in a minute.


Okay, here is one solution, using a derived RadioButton class that behaves purely with bindings: http://blogs.msdn.com/b/mthalman/archive/2008/09/04/wpf-data-binding-with-radiobutton.aspx

Here is a related SO question & answers: MVVM: Binding radio buttons to a view model?

Community
  • 1
  • 1
Jay
  • 56,361
  • 10
  • 99
  • 123
  • thanks for your response...I have tried executing without the setting IsRadioButton1,IsRadioButton to false...but still the result is the same. am unable to set the property of those once coming back to first or second radiobutton (for the third time of selection)..Can you please explain me more clearly, the way to resolve it..thanks again. – user1105705 Aug 27 '12 at 13:40
  • that's great..however, I need to know a single radiobutton's bool value for changing the visibility of the another control in the same form..which does not seems to be possible with above said process like setting a single property for both radiobuttons.....can you please let me know the process that has to be done in my given code if it is possible by anyways...thank you. – user1105705 Aug 27 '12 at 14:13
  • @Jay Can you please take a look at this? http://stackoverflow.com/questions/38434625/odd-behavior-when-trying-to-change-a-bound-radiobutton-in-wpf – Vahid Jul 18 '16 at 11:10