0

I have two radio buttons and are binding them to an enum Like in How to bind RadioButtons to an enum?

namespace RadioButtons
{
    public enum WorkModeEnum
    {
        Auto,
        Manual,
    }
}
<Window
    x:Class="RadioButtons.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:RadioButtons"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="800"
    Height="450"
    ContentRendered="Window_ContentRendered"
    mc:Ignorable="d">
    <Grid>
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
            <StackPanel.Resources>
                <local:EnumToBooleanConverter x:Key="ComparisonConverter" />
            </StackPanel.Resources>
            <RadioButton Content="Auto" IsChecked="{Binding Path=WorkMode, Mode=TwoWay, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static local:WorkModeEnum.Auto}}" />
            <RadioButton Content="Manual" IsChecked="{Binding Path=WorkMode, Mode=TwoWay, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static local:WorkModeEnum.Manual}}" />
        </StackPanel>
    </Grid>
</Window>

Code behind

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace RadioButtons
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private ViewModel _vm;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_ContentRendered(object sender, EventArgs e)
        {
            _vm = new ViewModel();
            DataContext = _vm;
        }
    }
}

The converter code looks like this

public class EnumToBooleanConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return ((Enum)value).HasFlag((Enum)parameter);
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return value.Equals(true) ? parameter : Binding.DoNothing;
        }
    }

ViewModel

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace RadioButtons
{
    public class ViewModel : INotifyPropertyChanged
    {
        public ViewModel()
        {
            WorkMode = WorkModeEnum.Manual;
        }

        private WorkModeEnum _WorkMode;

        public WorkModeEnum WorkMode
        {
            get { return _WorkMode; }
            set
            {
                _WorkMode = value;
                NotifyPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

It works, except for when the user click on the Manual button when it's already selected! Then both of the buttons will show selected!

enter image description here

Why and how fix it?

The whole project is accessible (hopefully, I have never done this before) at

https://github.com/Andis59/RadioButtons

Sir Rufo
  • 18,395
  • 2
  • 39
  • 73
Andis59
  • 559
  • 7
  • 25

1 Answers1

2

Your problem is the Converter. You are using a normal Enum but the converter treat it as [Flags] (which are a kind of different).

Enum.HasFlag(flag) will always return true if the ordinal value of the given flag is 0. Your WorkModeEnum.Auto has that ordinal value of 0 and causing this.

You could fix this by changing the WorkModeEnum definition to

public enum WorkModeEnum
{
    Auto = 1,
    Manual = 2,
}

but it is much better to fix the Converter

public class EnumToBooleanConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return ((Enum)parameter).Equals((Enum)value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value.Equals(true) ? parameter : Binding.DoNothing;
    }
}
Sir Rufo
  • 18,395
  • 2
  • 39
  • 73
  • This is what's happening when you copy code without understanding... Thank you very much! – Andis59 Feb 01 '22 at 12:57
  • Just in case you want to have more (and easier) binding, read https://brianlagunas.com/a-better-way-to-data-bind-enums-in-wpf/ – Sir Rufo Feb 01 '22 at 14:15