Odd behavior when trying to change a bound RadioBu

2019-03-01 11:23发布

问题:

I've bound two radio buttons in my Child window to an Enum in my ViewModel which is constructed in the Main window. The binding works as expected but I have noticed a very odd behavior which I can't solve. I have provided all the code here so you can reconstruct the problem easily for yourself.

Here are the steps to see this odd behavior:

  1. Click on the button in the MainWindow
  2. The ChildWindow opens and the RadioButton is set to User
  3. Choose Automatic and then Choose User again
  4. Close the ChildWindow and reopen it again! Try to change the RadioButton to Automatic. It won't change!
    <Window x:Class="RadioButtonBinding.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">

        <Button Content="Display Child Window" Click="DisplayChildWindow"/> 
    </Window>
    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();

            var viewModel = new ViewModel();
            DataContext = viewModel;
        }

        private void DisplayChildWindow(object sender, RoutedEventArgs e)
        {
            var win = new ChildWindow {DataContext = (ViewModel) DataContext};
            win.ShowDialog();
        }
    }
    <Window x:Class="RadioButtonBinding.ChildWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:radioButtonBinding="clr-namespace:RadioButtonBinding"
            Title="ChildWindow" Height="300" Width="300">
        <Window.Resources>
            <radioButtonBinding:EnumBooleanConverter x:Key="EnumBooleanConverter"/>
        </Window.Resources>

        <StackPanel>
            <RadioButton Content="Automatic" 
                         GroupName="CalcMode"
                         IsChecked="{Binding Path=CalcMode, 
                                             Converter={StaticResource EnumBooleanConverter}, 
                                             ConverterParameter={x:Static radioButtonBinding:CalcMode.Automatic}}"/>

            <RadioButton Content="Custom"
                         GroupName="CalcMode"
                         IsChecked="{Binding Path=CalcMode, 
                                             Converter={StaticResource EnumBooleanConverter}, 
                                             ConverterParameter={x:Static radioButtonBinding:CalcMode.User}}"/>
        </StackPanel>
    </Window>
    public class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;


        private CalcMode calcMode = CalcMode.User;
        public CalcMode CalcMode
        {
            get { return calcMode; }
            set
            {
                calcMode = value;
                RaisePropertyChanged("CalcMode");
            }
        }

        private void RaisePropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler == null) return;

            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    public class EnumBooleanConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var paramEnum = parameter as Enum;
            var valueEnum = value as Enum;

            return Equals(paramEnum, valueEnum);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var parameterEnum = parameter as Enum;
            if (parameterEnum == null)
                return DependencyProperty.UnsetValue;

            return parameterEnum;
        }
    }

    public enum CalcMode : byte
    {
        Automatic,

        User,
    }

UPDATE:

I suspect it must be the Converter but I don't know why? It just falls into a loop.

回答1:

EDIT What about converting the enum to bool as follows?

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
    if (parameter == null || !(bool)value)
        return DependencyProperty.UnsetValue;
    var parameterEnum = parameter as Enum;

    return parameterEnum;
}