trapemiyaの日記

hatenablogが新しくなったんで新規一転また2019年1月からちょこちょこ書いてます。C#中心のプログラミングに関するお話です。

RadioButtonのチェックがコードからCheckできなくなるバグはWPF4でも未だ直っていないようだ。

このバグは以下のコードで再現される。

<Window x:Class="test2010wpf.RadioButtonTest"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
           xmlns:local="clr-namespace:test2010wpf"    
        Title="RadioButtonTest" Height="150" Width="502">

    <Window.Resources>
        <local:BoolToByteConverter x:Key="boolToByteConverter" />
    </Window.Resources>
    
    <Grid>
        <StackPanel Margin="0,0,0,51">
            
            <RadioButton Content="RadioButton1" Height="16" Name="radioButton1"
                        IsChecked="{Binding OptionType, Converter={StaticResource boolToByteConverter}, ConverterParameter=1}" />
        
            <RadioButton Content="RadioButton2" Height="16" Name="radioButton2"
                        IsChecked="{Binding OptionType, Converter={StaticResource boolToByteConverter}, ConverterParameter=2}"/>
            
            <RadioButton Content="RadioButton3" Height="16" Name="radioButton3"
                        IsChecked="{Binding OptionType, Converter={StaticResource boolToByteConverter}, ConverterParameter=3}" />
        
        </StackPanel>
        
        <Button Content="Select RadioButton1" Height="23" HorizontalAlignment="Left" Margin="0,76,0,0" Name="button1"
                VerticalAlignment="Top" Width="132" Click="button1_Click" />
        <Button Content="Select RadioButton2" Height="23" HorizontalAlignment="Left" Margin="147,76,0,0" Name="button2"
                VerticalAlignment="Top" Width="132" Click="button2_Click" />
        <Button Content="Select RadioButton3" Height="23" HorizontalAlignment="Left" Margin="294,76,0,0" Name="button3"
                VerticalAlignment="Top" Width="132" Click="button3_Click" />
    </Grid>
</Window>
using System;
using System.Windows;
using System.Windows.Data;
using System.Globalization;

namespace test2010wpf
{
    /// <summary>
    /// RadioButtonTest.xaml の相互作用ロジック
    /// </summary>
    public partial class RadioButtonTest : Window
    {
        public RadioButtonTest()
        {
            InitializeComponent();
            this.DataContext = this;
        }

        // Dependency Property
        public static readonly DependencyProperty OptionTypeProperty =
                    DependencyProperty.Register("OptionType", typeof(byte), typeof(RadioButtonTest));

        // CLR Property Wrapper
        public byte OptionType
        {
            get { return (byte)GetValue(OptionTypeProperty); }
            set { SetValue(OptionTypeProperty, value); }
        }


        private void button1_Click(object sender, RoutedEventArgs e)
        {
            OptionType = 1;
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            OptionType = 2;
        }

        private void button3_Click(object sender, RoutedEventArgs e)
        {
            OptionType = 3;
        }
    }

    public class BoolToByteConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var v = (byte)value;

            if (v == byte.Parse(parameter.ToString()))
                return true;
            else
                return false;
        }
        
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return parameter;
        }
    }
}

上記のコードを実行すると以下の画面が表示される。

この画面でRadioButtonにチェックするために適当に「Select RadioButton1」、「Select RadioButton2」、「Select RadioButton3」を押していくと、
やがてそれらのボタンを押してもRadioButtonが反応しなくなる。これについては以下によればバグであり、WPF 4で既に修正されているとのことであるが、
私が試した限り、WPF 4でも修正されていない。

RadioButton unchecked bindings issue still not resolved? http://social.msdn.microsoft.com/forums/en-US/wpf/thread/8eb8280a-19c4-4502-8260-f74633a9e2f2/

このバグの対処としては、上記のリンク先に書いてある通り、異なるGroupNameを付ければ良い。つまり、以下のようにすれば良い。

    <RadioButton Content="RadioButton1" Height="16" Name="radioButton1"
                GroupName="a"
                IsChecked="{Binding OptionType, Converter={StaticResource boolToByteConverter}, ConverterParameter=1}" />

     <RadioButton Content="RadioButton2" Height="16" Name="radioButton2"
                GroupName="b"
                IsChecked="{Binding OptionType, Converter={StaticResource boolToByteConverter}, ConverterParameter=2}"/>

     <RadioButton Content="RadioButton3" Height="16" Name="radioButton3"
                GroupName="c"
                IsChecked="{Binding OptionType, Converter={StaticResource boolToByteConverter}, ConverterParameter=3}" />

しかし、上記の対処方法は、StackPanelを使わずにGroupNameを同じにすることによって3つのRadioButtonをグルーピングしている場合には使用できない。この場合の対処方法はいろいろ試した結果見つけたのであるが、以下のようにどのRadioButtonも取りえない値を一度セットすれば良いようだ。原因も何故うまく動くのかもわからなので保障はしませんがw

private void button1_Click(object sender, RoutedEventArgs e)
{
    OptionType = 255;
    OptionType = 1;
}

private void button2_Click(object sender, RoutedEventArgs e)
{
    OptionType = 255;
    OptionType = 2;
}

private void button3_Click(object sender, RoutedEventArgs e)
{
    OptionType = 255;
    OptionType = 3;
}