最近发现一个WPF里RadioButton的奇怪现象,由于在网上也没搜到合适的答案,遂记录一下:

现象:当一个对象集合里,对象的某些属性需要以RadioButton或者CheckBox的形式展现出来,并且会随着选择集合中不同的对象而变化时(如listbox,combobox),RadioButton绑定不会正确更新,而CheckBox则没问题;

这里以一个小例子来说明:

一个学生集合,每个学生其中包含一个性别属性Sex , 这里假如true表示男性,false表示女性:

    public class Student
        public int Age { get; set; }
        public string Name { get; set; }
        public bool Sex { get; set; }

使用一个StudentViewModel作为前端的datacontext ,默认先来3个学生:
  public class StudentViewModel
        public ObservableCollection<Student> Students { get; set; }
        public Student SelectedStudent { get; set; }
        public StudentViewModel()
            Students = new ObservableCollection<Student>();
            Students.Add(new Student() { Name="Tom",  Age=20,Sex=true});
            Students.Add(new Student() { Name = "Jack",  Age =21,Sex=false});
            Students.Add(new Student() { Name = "Ailien", Age =22,Sex=true});

前端用一个ListBox和两个radiobutton来展示,选择不同学生的时候, radiobutton的值不会根据我的选择来正确变化
<Window x:Class="WpfApplication4.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication4"
        xmlns:con="clr-namespace:WpfApplication4.Converters"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <con:InverseBooleanConverter x:Key="inverseBooleanConverter" />
    </Window.Resources>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <ListBox Grid.Column="0"  Width="200" ItemsSource="{Binding Students}" Height="400"
					 SelectedItem="{Binding SelectedStudent}" ScrollViewer.VerticalScrollBarVisibility="Visible">
            <ListBox.ItemTemplate>
                <DataTemplate>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="auto"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <TextBlock Text="{Binding Name}" Grid.Column="0" HorizontalAlignment="Left" />
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Grid Grid.Column="1">
            <Grid.RowDefinitions>
                <RowDefinition Height="20"></RowDefinition>
                <RowDefinition Height="20"></RowDefinition>
                <RowDefinition Height="40"></RowDefinition>
                <RowDefinition Height="20"></RowDefinition>
                <RowDefinition Height="20"></RowDefinition>
            </Grid.RowDefinitions>
	    <RadioButton x:Name="r1" Grid.Column="1" Grid.Row="0"  Margin="4,4,4,0" Content="Boy" IsChecked="{Binding SelectedStudent.Sex}"  GroupName="StudentSex" />
            <RadioButton x:Name="r2" Grid.Column="1" Grid.Row="1"   Margin="4,4,4,0" Content="Girl" IsChecked="{Binding SelectedStudent.Sex,Converter={StaticResource inverseBooleanConverter}}" GroupName="StudentSex" />
	   <Button x:Name="button" Content="Button" HorizontalAlignment="Left" Height="60" Margin="72,105,0,-144" Grid.Row="4" VerticalAlignment="Top" Width="120" RenderTransformOrigin="0.5,0.5" Click="button_Click">
                <Button.RenderTransform>
                    <TransformGroup>
                        <ScaleTransform/>
                        <SkewTransform/>
                        <RotateTransform Angle="11.937"/>
                        <TranslateTransform/>
                    </TransformGroup>
                </Button.RenderTransform>
            </Button>
        </Grid>
    </Grid>
</Window>

其中Converter代码为:

 public class InverseBooleanConverter : MarkupExtension, IValueConverter
        #region IValueConverter Members
        public object Convert(object value, Type targetType, object parameter,
            System.Globalization.CultureInfo culture)
            bool boolVal = value == null ? false : (bool)value;
            return !boolVal;
        public object ConvertBack(object value, Type targetType, object parameter,
            System.Globalization.CultureInfo culture)
            if (targetType != typeof(bool) && targetType != typeof(Visibility) && targetType != typeof(bool?))
                throw new NotSupportedException();
            return !(bool)value;
        public override object ProvideValue(IServiceProvider serviceProvider)
            return this;
        public InverseBooleanConverter() : base()
        #endregion

但是如果把两个radiobutton换成CheckBox就没问题,每次选择学生都能够根据选择的学生正确显示性别

<CheckBox Grid.Column="1" Grid.Row="3" Content="Boy" IsChecked="{Binding SelectedStudent.Sex}"></CheckBox>
<CheckBox Grid.Column="1" Grid.Row="4" Content="Girl" IsChecked="{Binding SelectedStudent.Sex, Converter={StaticResource inverseBooleanConverter}}" />

猜想可能是RadioButton和CheckBox内部原理不太一样,因为每次选择不同学生时,Radiobutton会时不时进入到ConvertBack函数中去,导致属性值错乱,而CheckBox则不会;

于是试着给每个RadioButton加上Mode=OneWay,因为RadioButton默认是TwoWay, 改完发现上面的问题没有了,能够正确更新状态,但是手动选择却不能使后台数据源属性生效了,最后发现只要给第二个RadioButton加上UpdateSourceTrigger=Explicit所有问题都解决了,后台也能根据前端界面值更改而更改:

<RadioButton x:Name="r2" Grid.Column="1" Grid.Row="1"   Margin="4,4,4,0" Content="Girl" IsChecked="{Binding SelectedStudent.Sex,Converter={StaticResource inverseBooleanConverter},UpdateSourceTrigger=Explicit}" GroupName="StudentSex" />

原来UpdateSourceTrigger=Explicit是强制手动去call UpdateSource代码才使得后台数据生效,加上就相当于不要去更新第二个RadioButton的后台值,仅针对两个控件绑定一个属性的情况。

If you set the UpdateSourceTrigger value to Explicit, you must call the UpdateSource method or the changes will not propagate back to the source.

这么一想,还有一种同样的办法,就是给第二个RadioButton加上Mode=OneWay:

<RadioButton x:Name="r2" Grid.Column="1" Grid.Row="1"   Margin="4,4,4,0" Content="Girl" IsChecked="{Binding SelectedStudent.Sex,Converter={StaticResource inverseBooleanConverter},Mode=OneWay}" GroupName="StudentSex" />

都能够解决问题。 最近发现一个WPF里RadioButton的奇怪现象,由于在网上也没搜到合适的答案,遂记录一下:现象:当一个对象集合里,某些属性需要以RadioButton或者CheckBox的形式展现出来,并且会随着切换集合中的对象而变化时,RadioButton绑定不会正确更新,而CheckBox则没问题;这里以一个小例子来说明:一个学生集合,每个学生其中包含一个性别属性S where T : struct, IConvertible private static Dictionary<int, Tuple<T, string>> collectionCache; <StackPanel Margin="10"> <Label FontWeight="Bold">Are you ready?</Label> <RadioButton>Yes</RadioButton>   申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接。 本文主要内容: CheckBox复选框的自定义样式,有两种不同的风格实现; RadioButton单选框自定义样式,有两种不同的风格实现; 二. CheckBox自定义样式 2.1 CheckBox...
WPF提供了许多包装集合的控件。这里包括了ListBox列表控件、ComboBox组合框控件,还有其他的更多的空间我们就不介绍了。 ListBox是个典型的ItemsControl。 首先,我们看看ListBox的自动包装。WPF的ListBox在显示功能上比Winform Form或 者ASP.NET的ListBox要强大很多。传统的ListBox只能将条目以字符串的形式显示,而 WPF的ListBox除了可以显示中规中矩的字符串条目还能够显示更多的元素, 如CheckBoxButtonRadioBu
刚玩WPF不多久,来到一家新公司 因为现在工作轻松一点就安排了我去做DataGrid的增删改查功能的实现,因为是底层封装好的原因就不方便贴代码了,但对于像我这样的小白来说,工作中有很多我们还没接触过的存在 就已ChexkBox举例吧! CSDN-Ada助手: 非常棒的技术分享!绘制高清图是很多开发者都会遇到的问题,希望你能继续分享你的经验和技巧。不妨考虑下一篇博客,介绍如何使用 WPF 实现图像处理的功能,例如图像缩放、旋转、裁剪等。这样的主题一定会吸引到更多的读者,并且为他们带来实用的技术指导。期待你的新作品! 为了方便博主创作,提高生产力,CSDN上线了AI写作助手功能,就在创作编辑器右侧哦~(https://mp.csdn.net/edit?utm_source=blog_comment_recall )诚邀您来加入测评,到此(https://activity.csdn.net/creatActivity?id=10450&utm_source=blog_comment_recall)发布测评文章即可获得「话题勋章」,同时还有机会拿定制奖牌。 C语言:行指针和列指针 int main( ): 博主你好,请问数组指针的方括号里的数字为什么取决于二维数组的列 C语言:行指针和列指针 晚安苏州: 1. 其实没什么用,不用const也没问题,只是为了防止引用参数无意中被篡改;2. 也不一定,其实没有什么一级二级指针,只是习惯叫法,不是什么标准; 3.指针的指针和数组的指针在内存中的排布是不一样的,可以上网自己查查。 C语言:行指针和列指针 承诺$枷锁: 我有三个问题哈:①就是为什么用很多const,这是一种习惯吗?②就是 *example是一级指针吗?怎么算的,是否可以这么理解,就是 example 相当于二级地址,取 * 就变成一级指针了吗?③最后一个类型不匹配我看不出来耶表情包。wrongFunc(example,3,5)传的不就是一个二级地址吗,与二级指针等价,为啥子显示是int (*)[5]这个一级指针呢?求博主大大解答,感谢