使用WPF绑定后台数据,在多次切换数据后绑定失效
将一个后台数据绑定到多个RadioButton的IsChecked上,通过自定义转换将整型数据转换成bool型数据。点击界面上的新增按钮,在button事件中,将绑定的对象数据加1,然后再前台显示,在多次后,前台的RadioButton中会出现某个绑定失败问题。
自定义转换器代码:
#region 方法
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value != null)
{
try
{
if (parameter != null)
{
int par = 0;
if (int.TryParse(parameter.ToString(), out par))
{
return (value as int?).Value - par == 0;
}
return false;
}
else
return false;
}
catch (System.Exception)
{
return false;
}
}
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
try
{
if (parameter != null)
{
int par = 0;
if (int.TryParse(parameter.ToString(), out par))
{
if ((bool)value)
return par;
return null;
}
return 0;
}
else
{
return (bool)value ? 1 : 0;
}
}
catch (System.Exception)
{
}
return null;
}
#endregion
XAml代码:
<DockPanel x:Name="grid" LastChildFill="False">
<DockPanel.DataContext>
<local:Student/>
</DockPanel.DataContext>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" HorizontalAlignment="Center" >
<Button HorizontalAlignment="Center" Width ="60" Height="60" Click="Add_Click" Content="新增"/>
<Button HorizontalAlignment="Center" Width ="60" Height="60" Click="Delete_Click" Content="删除"/>
</StackPanel>
<RadioButton x:Name="rbtn_4" Content="test4" DockPanel.Dock="Top" IsChecked="{Binding Age, ConverterParameter=1, Converter={StaticResource IntToBoolConverter}}" GroupName="test2" Margin="0,10,0,0"/>
<RadioButton x:Name="rbtn_5" Content="test5" DockPanel.Dock="Top" IsChecked="{Binding Age, ConverterParameter=2, Converter={StaticResource IntToBoolConverter}}" GroupName="test2"/>
<RadioButton x:Name="rbtn_6" Content="test6" DockPanel.Dock="Top" IsChecked="{Binding Age, ConverterParameter=3, Converter={StaticResource IntToBoolConverter}}" GroupName="test2"/>
<RadioButton x:Name="rbtn_7" Content="test7" DockPanel.Dock="Top" IsChecked="{Binding Age, ConverterParameter=4, Converter={StaticResource IntToBoolConverter}}" GroupName="test2"/>
<TextBox DockPanel.Dock="Top" Margin="0,10,0,0" Text="{Binding Age, ConverterParameter=1, Converter={StaticResource IntToBoolConverter}}"></TextBox>
<TextBox DockPanel.Dock="Top" Margin="0,10,0,0" Text="{Binding Age, ConverterParameter=2, Converter={StaticResource IntToBoolConverter}}"></TextBox>
<TextBox DockPanel.Dock="Top" Margin="0,10,0,0" Text="{Binding Age, ConverterParameter=3, Converter={StaticResource IntToBoolConverter}}"></TextBox>
<TextBox DockPanel.Dock="Top" Margin="0,10,0,0" Text="{Binding Age, ConverterParameter=4, Converter={StaticResource IntToBoolConverter}}"></TextBox>
</DockPanel>
前台代码:
private void Add_Click(object sender, RoutedEventArgs e)
{
Student tstd = grid.DataContext as Student;
tstd.Age = tstd.Age % 4 + 1;
}
Student:
class Student : INotifyPropertyChanged
{
#region 属性
string name;
public string Name
{
get { return name; }
set
{
name = value;
if (this.PropertyChanged != null)
{
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name"));
}
}
}
public String ID
{
set;
get;
}
int age = 1;
public int Age
{
set
{
if (value == -1)
return;
age = value;
if (this.PropertyChanged != null)
{
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Age"));
}
}
get { return age; }
}
IP ip = new IP("127.0.0.1");
public IP IP
{
get { return ip; }
set
{
ip = value;
if (this.PropertyChanged != null)
{
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("IP"));
}
}
}
#endregion
#region 方法
public Student Clone()
{
Student stu = new Student();
stu.Name = this.Name;
stu.Age = this.Age;
stu.ID = this.ID + 1;
return stu;
}
#endregion
#region 事件
#endregion
public event PropertyChangedEventHandler PropertyChanged;
}
目前的解决方案是使用CheckBox代替Radiobutton,同时针对CheckBox的Click方法额外处理(禁用Check的取消选中功能)。
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
(sender as CheckBox).IsChecked = true;
e.Handled = true;
}
多个CheckBox之间的单选性采用绑定到同一个变量来处理(使用到上面的自定义转换器)。
猜测:
单选按钮同一组内按钮的是否选中是关联的,在你选中其中某个项时,底层会将其他选项的IsChecked属性进行更新,此时与绑定冲突照成绑定的失效,而CheckBox是否选中只针对自己。