Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF + MVVM + RadioButton : Handle binding with single property

From this and this (and other) questions on SO and many other material on internet, I understood how to bind radio button with VM.

But all of them create separate property for each possible value of radio button. One question (this) is similar to my requirement but the accepted answer suggests to use ListBox instead of radio button.

To represent person gender (Datatype CHAR, Possible values 'M', 'F'), three properties needs to be created in VM as PersonGender, IsPersonMale, IsPersonFemale. I want to control this on only one property PersonGender. Can I do this? If yes, how?

like image 417
Amit Joshi Avatar asked Jun 13 '16 12:06

Amit Joshi


2 Answers

You need a converter.

//define this in the Window's Resources section or something similiarly suitable
<local:GenderConverter x:Key="genderConverterKey" />


<RadioButton Content="M" IsChecked="{Binding Gender, Converter={StaticResource ResourceKey=genderConverterKey}, ConverterParameter=M}" />
<RadioButton Content="F" IsChecked="{Binding Gender, Converter={StaticResource ResourceKey=genderConverterKey}, ConverterParameter=F}" />

The converter

public class GenderConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return ((string)parameter == (string)value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return (bool)value ? parameter : null;        
    }
}

Replace null (in ConvertBack) with Binding.DoNothing if binding should not be applied in that case.

return (bool)value ? parameter : Binding.DoNothing;
like image 138
user2880486 Avatar answered Oct 20 '22 23:10

user2880486


Use Commands (Using DelegateCommands here)

VM:

public enum Genders {
    Female,
    Male
}
public YourVMClass {
    public Genders SelectedGender {get; set;}

    private DelegateCommand _cmdSelectGender;

    public DelegateCommand CmdSelectGender {
        get { return _cmdSelectGender ?? (_cmdSelectGender = new DelegateCommand(SelectGender)); }
    }

    private void SelectGender(Object parameter) {
        SelectedGender = (Genders)parameter;
    }
}

XAML:

<Window.Resources>
    <ObjectDataProvider x:Key="listOfGenders" MethodName="GetValues"
                        ObjectType="{x:Type System:Enum}">
        <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="loca:Genders"/>
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
</Window.Resources>

<ItemsControl ItemsSource="{Binding Source={StaticResources listOfGenders}}">
    <ItemsControl.ItemTemplate>
        <RadioButton GroupName="Genders" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type MainWindow}}, Path=DataContext.CmdSelectGender}" CommandParameter="{Binding}"/>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

(Didn't test the code, but this is the idea)

like image 30
nkoniishvt Avatar answered Oct 21 '22 00:10

nkoniishvt