Determining checked Radiobutton from groupbox in WPF following MVVM
Asked Answered
H

5

16

I have a groupbox with some radiobuttons. How do I get to know which one which is checked? I am using WPF and following MVVM.

<GroupBox Name="grpbx_pagerange" Header="Print Range">
    <Grid >
        <RadioButton Name="radbtn_all" Content="All Pages" GroupName="radios_page_range" IsChecked="True"  />
        <RadioButton x:Name="radbtn_curr" Content="Current Page" GroupName="radios_page_range"  />
        <RadioButton Name="radbtn_pages" Content="Page Range" GroupName="radios_page_range" />

        ....

</GroupBox>

Now, one way I could figure out was to bind each RadioButton's IsChecked Property to some property in ViewModel and then do if..else sort of logic in my ViewModel to figure out the selected radiobutton.

But Is there any other elegant way?

Hejaz answered 4/9, 2013 at 14:35 Comment(0)
V
39

you can bind RadioButton.Command of Radiobuttons to a command of your ViewModel and send a unique CommandParameter to identify which button has called the command in commandhandler.

<RadioButton Command="{Binding MyCommand}" CommandParameter="Radio1"/>
<RadioButton Command="{Binding MyCommand}" CommandParameter="Radio2"/>
<RadioButton Command="{Binding MyCommand}" CommandParameter="Radio3"/>

in command handler check for parameter to identify the radiobutton.

Thanks

Vietcong answered 4/9, 2013 at 14:53 Comment(5)
Hi @nit : This is very simple, quick, elegant and indeed worth applying solution. Thanks for your answer. :)Hejaz
Buddy, The solution works fine, BUT how would i set default checked to any of my RadioButton. Well we can set it in the contructor , but that would VIOLATE MVVM rules. Any ideas would be helpful .Hejaz
if checked state of your radiobutton are not data driven i.e if open your print dialog everytime with default option then setting IsChecked=true on first radiobutton in xaml wont sting. :)Vietcong
Hey @nit: I think your answer points out that I'm not KISS-(thinking complx). Thanks Again, It helped. :)Hejaz
But what if checked state is data driven? How can I make some of the buttons to be checked? I have tried this in xaml: IsChecked="{Binding Button.Checked, Mode=TwoWay}" But it didn't helped. /Thanks for helpInterpretive
D
21

You can create an enum that contains the values of the RadioButton objects as names (roughly) and then bind the IsChecked property to a property of the type of this enum using an EnumToBoolConverter.

public enum Options
{
    All, Current, Range
}

Then in your view model or code behind:

private Options options = Options.All; // set your default value here

public Options Options
{ 
    get { return options; }
    set { options = value; NotifyPropertyChanged("Options"); }
}

Add the Converter:

[ValueConversion(typeof(Enum), typeof(bool))]
public class EnumToBoolConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null || parameter == null) return false;
        string enumValue = value.ToString();
        string targetValue = parameter.ToString();
        bool outputValue = enumValue.Equals(targetValue, StringComparison.InvariantCultureIgnoreCase);
        return outputValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null || parameter == null) return null;
        bool useValue = (bool)value;
        string targetValue = parameter.ToString();
        if (useValue) return Enum.Parse(targetType, targetValue);
        return null;
    }
}

Then finally, add the bindings in the UI, setting the appropriate ConverterParameter:

<RadioButton Content="All Pages" IsChecked="{Binding Options, Converter={
    StaticResource EnumToBoolConverter}, ConverterParameter=All}" />
<RadioButton Content="Current Page" IsChecked="{Binding Options, Converter={
    StaticResource EnumToBoolConverter}, ConverterParameter=Current}" />
<RadioButton Content="Page Range" IsChecked="{Binding Options, Converter={
    StaticResource EnumToBoolConverter}, ConverterParameter=Range}" />

Now you can tell which is set by looking at the Options variable in your view model or code behind. You'll also be able to set the checked RadioButton by setting the Options property.

Declivous answered 4/9, 2013 at 15:10 Comment(5)
Hey @Sheridan: Your solution looks great , especially the Enum & Converterfeature . But I ain't able allocate the static resource in Window.Resource - it would be usable - if you could please add your view of defining the static resource. Thanks. :)Hejaz
@Bhramar you can include the converter like this: first include xml namespace like xmlns:local=="clr-namespace:WpfApplication1" i,e then namespace in which converter is declared. then in Window.Rsources add <local:EnumToBoolConverter x:Key="EnumToBoolConverter"/>Vietcong
I have tried this: <Window x:Name="win_printDialog" x:Class="M.N.Core.Control.DocumentPrintDialog" ... xmlns:local="clr-namespace:M.N.Core.Control" Title="Print Dialog" > <Window.Resources> <local:EnumToBoolConverter x:Key="EnumToBoolConverter" /> </Window.Resources> This is just so not working. I referred this article Error says-"The EnumToBoolConverter" does not exist in the namespace "clr-namespace:M.N.Core.Control"Hejaz
A slight change I made to this approach was to return Binding.DoNothing rather than null - otherwise what I was seeing was a red validation border around the un-checked radio buttons. Seemed to fix things for me.Sipe
Yeah, another popular option is to return DependencyProperty.UnsetValue... it's up to you which you prefer.Declivous
P
1

There is another MVVM way to solve this using IsChecked Property

Here's the XAML

<Page>
<Page.Resources>
<DataTemplate x:Key="ChoiceItemTemplate">
<RadioButton Content="{Binding individualRadioButtonText}"
     IsTabStop="True"
     GroupName="choice"
     IsChecked="{Binding IsChecked, Mode=TwoWay}"/>
 </DataTemplate>
</Page.Resources>


 <StackPanel>
  <TextBlock Text="{Binding ChoiceQuestion}" />
 <ItemsControl  ItemsSource="{Binding ListOfAnswerOptions}"
                ItemTemplate="{StaticResource ChoiceItemTemplate}" />
 </StackPanel>
</Page>

Your model will be something like this

 public class RadioButtonQuestion
 {
    public string ChoiceQuestion { get; set; }
    public string answer { get; set; }
    public List<AnswerOption> ListOfAnswerOptions { get; set; }
 }

 public class AnswerOption
 {
    public string individualRadioButtonText { get; set; }
    public bool IsChecked { get; set; }
 }

ViewModel will look something like this (The selection logic)

RadioButtonQuestion r = new RadioButtonQuestion();
var selectedElement = rbuttonQuestion.answerOptions.FirstOrDefault(c => c.IsChecked);
r.answer = selectedElement.individualRadioButtonText;

So if you set the datacontext of the view to this viewmodel. You must be able to get it to work.

Hope it helps.

Peden answered 10/7, 2014 at 19:13 Comment(0)
H
1

If you use Tag property on options buttons (boolean, integer, strings) like in his XAML

<StackPanel Orientation="Horizontal" Margin="10,10, 0, 0">
    <RadioButton Name="rP0" Content="Low  " Tag="0" />
    <RadioButton Name="rP1" Content="Normal" Tag="1" IsChecked="True" />
    <RadioButton Name="rP2" Content="Medium" Tag="2" />
    <RadioButton Name="rP3" Content="High" Tag="3" />
</StackPanel>

Then you can use following function to get selected value (button)

int priority = SelectedRadioValue<int>(0, rP0, rP1, rP2, rP3);

where

public T SelectedRadioValue<T>(T defaultValue, params RadioButton[] buttons)
{
    foreach (RadioButton button in buttons)
    {
        if (button.IsChecked == true)
        {
            if (button.Tag is string && typeof(T) != typeof(string))
            {
                string value = (string) button.Tag;
                return (T) Convert.ChangeType(value, typeof(T));
            }

            return (T)button.Tag;
        }
    }

    return defaultValue;
}
Hubbub answered 29/1, 2016 at 13:43 Comment(0)
A
-4

I got same problem and i solved by removing "GroupName" Property from Radiobutton.

Please remove "GroupName" Property from all radio buttons. and check

Altman answered 18/11, 2013 at 12:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.