0
votes

I want to bind (TwoWay) a string value ("True" or "False") to two radio buttons with Content "True" and "False".

Conditions

  1. When use select "True" RadioButton , string value should be "True" and vice versa for "False" radio button.
  2. At a time only one RadioButton is selectable either True or False.
  3. There is list of string and Radio Buttons are part of DataTemplate.

XAML

<Grid.RowDefinitions>
    <RowDefinition Height="*"/>
    <RowDefinition Height="Auto"/>
</Grid.RowDefinitions>

<ListBox ItemsSource="{Binding Values}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <RadioButton x:Name="rbTrue" Content="True" IsChecked="{Binding Value,Mode=TwoWay}" />
                <RadioButton x:Name="rbFalse" Content="False" IsChecked="{Binding Value,Mode=TwoWay}"/>
            </StackPanel>
        <DataTemplate.Triggers>
            <DataTrigger Binding="{Binding Path=Value,Mode=TwoWay}" Value="True">
                <Setter Property="IsChecked" TargetName="rbTrue" Value="True"/>
                <Setter Property="IsChecked" TargetName="rbFalse" Value="False"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=Value,Mode=TwoWay}" Value="False">
                <Setter Property="IsChecked" TargetName="rbTrue" Value="False"/>
                <Setter Property="IsChecked" TargetName="rbFalse" Value="True"/>
            </DataTrigger>
        </DataTemplate.Triggers>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

XAML.CS

public partial class MainWindow : Window
{
    MainViewModel viewModel;

    public MainWindow()
    {
        InitializeComponent();

        viewModel = new MainViewModel();

        this.DataContext = viewModel;
    }
}

VIEWMODEL

public class MainViewModel : ModelBase
{
    private List<MainModel> values;
    public List<MainModel> Values
    {
        get
        {
            return values;
        }
        set
        {
            if (value != values)
            {
                values = value;
                OnPropertyChanged("Values");
            }
        }
    }

    public MainViewModel()
    {
        Values = new List<MainModel>();

        for (int i = 0; i < 10; i++)
        {
            if (i % 2 == 0)
                Values.Add(new MainModel() { Value = true });
            else
                Values.Add(new MainModel() { Value = false });
        }
    }
}

MODEL

public class MainModel : ModelBase
{
    private bool strValue;
    public bool Value
    {
        get
        {
            return strValue;
        }
        set
        {
            if (value != strValue)
            {
                strValue = value;
                OnPropertyChanged("Value");
            }
        }
    }
}

MODELBASE

public abstract class ModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }
}

UI

enter image description here

I almost tried everything I know and also checked most of the relative links online on different forum and other material.

All I want is value either "True" or "False" based in user selection in list.

Thanks in advance.

1
Wouldn't it be a lot simpler to use a single ToggleButton or CheckBox?Clemens
@Clemens I need to use radio buttons only.Gaurang Dave

1 Answers

1
votes

I am assuming you meant "bind (TwoWay) Boolean value to two radio buttons" instead of "bind (TwoWay) string to two radio buttons", since Value has the data type bool.

First, do not use the DataTriggers; remove them.

Instead, on the binding for the "false" button, add a converter that negates the boolean value:

<RadioButton x:Name="rbFalse" Content="False" IsChecked="{Binding Value,Mode=TwoWay,Converter={StaticResource NegateConverter}}"/>

In your XAML resources, you need to define the converter:

<local:NegateConverter x:Key="NegateConverter"/>

Replace local by whatever namespace you defined the NegateConverter class in.

Here is the code for the converter:

/// <summary>
/// This converter negates a boolean value.
/// </summary>
[ValueConversion(typeof(bool), typeof(bool))]
public class NegateConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        bool bValue = false;
        if (value is bool)
        {
            bValue = (bool)value;
        }
        return !bValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        bool bValue = false;
        if (value is bool)
        {
            bValue = (bool)value;
        }
        return !bValue;
    }
}