Jake
Jake

Reputation: 1781

Validation on Radio Buttons

I'm not really sure how to word this, so here goes.

I've got some radio buttons on a form in my WPF application which get validated. They're basically a required field for this form.

When I start to fill in the form, both radio buttons are marked with a red border, however when I select one of the buttons. This happens:

enter image description here

How do I go about fixing this? I know I could change the control to something like a ComboBox or something, but typically gender fields on an electronic form are radio buttons.

I've tried getting the validation to display on the stackpanel containing the radio buttons, it's done nothing.

I can't really set a default value for the gender either incase it gets overlooked and causes a complaint/misunderstanding further down the line.

The XAML for the image above is here:

<StackPanel Grid.Column="1" Grid.Row="3" Orientation="Horizontal">
    <RadioButton GroupName="Gender" Content="Male" IsChecked="{Binding Gender, Converter={StaticResource GenderToCharConverter}, ConverterParameter=M}"/>
    <RadioButton GroupName="Gender" Content="Female" IsChecked="{Binding Gender, Converter={StaticResource GenderToCharConverter}, ConverterParameter=F}"/>
</StackPanel>

Edit: To clarify a bit more on what my problem is, when I open a new instance of this form, both radio buttons are marked with validation borders as they should be as Gender is a required field on this form.

When a gender is selected, the validation border is only removed from the radio button that is clicked when really I would imagine that both borders should be removed as the data-bound property now has a value.

The only way it seems to remove this border is to click the other option to remove and then re-select the original value. This shouldn't happen on this form as this could confuse the users and have them mistakingly think that there's still a problem with the gender controls, and furthermore it just looks like a bug.

Edit 2: This question fixes the border showing, but then hides the fact that one of the radio buttons selected is required. Is there not some way to put a border around the StackPanel instead rather than the individual radio buttons. It seems there is absolutely no examples on how to achieve this on Google, which is completely stupid.

Edit 3: Relevant code.

// Gender property in the viewmodel.
[Required(AllowEmptyStrings=false, ErrorMessage="Gender is a required field.")]
    public string Gender
    {
        get { return _currentMember.Gender; }
        set
        {
            if(value != _currentMember.Gender)
            {
                _currentMember.Gender = value;
                RaisePropertyChanged();
                Validate(_currentMember.Gender);
            }
        }
    }

// Converter
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
            string input = (string)value;
            string test = (string)parameter;
            return input == test;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null || !(value is bool))
            return string.Empty;

        if (parameter == null || !(parameter is string))
            return string.Empty;

        if ((bool)value)
            return parameter.ToString();

        else
            return string.Empty;
    }

Upvotes: 4

Views: 4034

Answers (2)

Robin Bennett
Robin Bennett

Reputation: 3231

Here's how to do this without the framework in the other answer (which is nice but not essential).

The key is to surround the radio buttons with another element, which has a binding to the same property. This will display the error. I set a binding for the Tag property of a StackPanel, which is otherwise not used.

Then you need to turn off the validation error template for each radio button, using 'Validation.ErrorTemplate="{x:Null}"'.

<StackPanel Tag="{Binding Gender}" >
    <RadioButton IsChecked="{Binding Gender, 
        Converter={StaticResource GenderConverter},
        ConverterParameter={x:Static enumerations:Male}}" 
        Content="Male" Validation.ErrorTemplate="{x:Null}"/>
    <RadioButton IsChecked="{Binding Gender, 
        Converter={StaticResource GenderConverter},
        ConverterParameter={x:Static enumerations:Female}}" 
        Content="Female" Validation.ErrorTemplate="{x:Null}"/>
</StackPanel>

Upvotes: 2

Il Vic
Il Vic

Reputation: 5666

In my opinion you have 2 solutions: the first one - the easiest one - is to set a default for Gender property. In this way one among the two radiobuttons will be check and the "required" attribute will be always satisfied.

The second solution is to "mask" a ListView as a RadioButtonGroup. For my example I used a very intuitive framework to perform validation by using attributes. You can find it here.

So, instead of using a stackpanel, I wrote this piece of XAML:

<ListView SelectedValue="{Binding Gender, ValidatesOnDataErrors=True}"
            SelectedValuePath="Tag" BorderThickness="0" Margin="2" SelectionMode="Single">

    <RadioButton GroupName="Gender" Margin="2" Tag="M" Content="Male" IsChecked="{Binding RelativeSource={RelativeSource AncestorType=ListViewItem}, Path=IsSelected}" />
    <RadioButton GroupName="Gender" Margin="2" Tag="F" Content="Female" IsChecked="{Binding RelativeSource={RelativeSource AncestorType=ListViewItem}, Path=IsSelected}" />

</ListView>

Of course the ListView can be improved with a more suitable style (which for example hides the selection style). Since just the SelectedValue property is binded to the Gender property, you will see just one validation template around the ListView.

I hope this is the result you were looking for.

Moreover - with the that framework - I could not reproduce your issue, since if I use your stackpanel and I check one radiobutton, both the red rectangles will disappear.

Upvotes: 4

Related Questions