2017-04-06 55 views
-1

设置时,我有一个单选按钮布尔整数转换器类:布尔值,整数转换问题,从视图模型

public class RadioBoolToIntConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, 
          CultureInfo culture) 
    { 
     int integer = (int)value; 
     if (integer == int.Parse(parameter.ToString())) 
      return true; 
     else 
      return false; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, 
           CultureInfo culture) 
    {    
     return parameter; 
    } 
} 

我有一个绑定到一个属性“TestTypeRef”一个StackPanel内的两个单选按钮:

<StackPanel Orientation="Horizontal"> 
    <RadioButton 
     Content="Screening" 
     Margin="0 0 10 0" 
     IsChecked="{Binding Path=TestTypeRef, Mode=TwoWay, Converter={StaticResource RadioBoolToIntConverter}, ConverterParameter=0 }" /> 
    <RadioButton 
     Content="Full" 
     Margin="0 0 10 0" 
     IsChecked="{Binding Path=TestTypeRef, Mode=TwoWay, Converter={StaticResource RadioBoolToIntConverter}, ConverterParameter=1 }" /> 
</StackPanel> 

当我尝试在关联的ViewModel中设置绑定了单选按钮的属性的值时,会出现问题。

当我将值从0设置为1时 - 这很好。

当我设置从1到0值 - 属性值保持1:

视图模型内部:

// Set the default test type. 
TestTypeRef = 0; 
// ~~> TestTypeRef = 0 
TestTypeRef = 1; 
// ~~> TestTypeRef = 1   
TestTypeRef = 0; 
// ~~> TestTypeRef = 1 i.e. no change. 

非常感谢您能提供任何帮助。

更新: 感谢@Rachel和@Will的反馈意见。 ConvertBack例程出错。固定它:

return value.Equals(false) ? DependencyProperty.UnsetValue : parameter; 
+0

在转换你的'ConvertBack'方法总是返回'ConverterParameter'的价值,所以它总是将是0或1,这取决于你的UI将其设置为。这看起来是错误的,并且闻起来像它跟你观察到的东西有关。你应该正确地实现ConvertBack方法,或者当你往返UI时看看里面发生了什么。 – Will

+0

Hi @Will。是的 - 在ConvertBack方法中的错误。谢谢你的评论。 – AndyS

回答

1

我想你可能被错误地使用一个转换器,但我不知道我理解你原来的前提。

转换器用于将绑定值转换为不同类型。所以,你的转换器是说当它读取从器isChecked UI的财产,是

“比较限值(TestTypeRef)给定的参数。如果同样的,检查单选按钮”

它也说,做反向转换(写值器isChecked回绑定值(TestTypeRef),只是

时“发回的参数值”

所以要做逻辑...

当UI绑定值读取器isChecked财产

 
If TestTypeRef is equal to 0 

    Radio 0 is checked because the value equals the parameter (0) 
    Radio 1 is unchecked because the value does not equal the parameter (1) 

If TestTypeRef is equal to 1 

    Radio 0 is unchecked because the value does not equals the parameter (0) 
    Radio 1 is checked because the value equals the parameter (1) 

现在问题就来为您的反向绑定,当它写入值回数据源

 
If Radio 0 is checked, write 0 to the datasource 
If Radio 0 is unchecked, write 0 to the datasource 
If Radio 1 is checked, write 1 to the datasource 
If Radio 1 is unchecked, write 1 to the datasource 

当您将数据源值设置为某种值,它会触发IsChecked值的更新,然后写回数据源

 
Default : TestTypeRef = 0 
    Radio 0 is checked 
    Radio 1 is unchecked 

Set TestTypeRef = 1 
    Update Radio 0 Binding (Checked > Unchecked) 
    Update Radio 1 Binding (Unchecked > Checked) 

Because the IsChecked updates, it uses ConvertBack to update the data source. 
    If Radio 1 is checked, write 1 to the datasource 

请注意,此时,Radio0绑定的更改事件不会运行,可能是因为它现在看到没有任何更改 - 更改事件已引发,但值从1变为1,因此它不运行代码更新任何东西。

您可以通过在ConvertBack方法中放置一个断点来确认这一点,并且您会注意到,当您尝试将该值设置为0时,它将被命中值为“1”。设置器TestTypeRef中的另一个断点将还会显示它先将值更改为0,然后再次更改为1。

长话短说,修复你的转换器。或者更好的是,修复你的设计。

从我可以告诉你,你试图说“如果界限值等于某个值,isChecked是真实的”,但是从这个陈述你不能准确地得到反向。如果用户检查单选按钮,那么您设置的界限值等于参数。如果用户取消选中单选按钮,则不知道如何设置绑定值。

因此,无论

  1. 更改绑定的单向所以他们永远不会运行ConvertBack和更新数据源。如果您希望用户真正使用单选按钮,这并不理想。
  2. 所以它以正确的方式格式化 显示的数据,如所谓的IsFull 2个布尔属性和 IsScreening你可以直接
  3. 绑定实现一个更好的一套这个 UI控件
  4. 更改限值。我个人的偏好是ListBox bound to a single value and styled with RadioButtons,但这对于本质上是一种价值的东西可能是过分的。

就我个人而言,我会为你现在建议2。

public bool IsScreening 
{ 
    get { return TestTypeRef == 0; } 
    set { if (value) TestTypeRef = 0; } 
} 

public bool IsFull 
{ 
    get { return TestTypeRef == 1; } 
    set { if (value) TestTypeRef = 1; } 
} 
+0

谢谢@Rachel,感谢您的精彩演讲。 ConvertBack例程出错。这固定它: 返回值.Equals(false)? DependencyProperty.UnsetValue:参数; – AndyS

0

我们将需要使用转换器参数来指定单选按钮对应的值。如果你的财产等于这个值,那么这个按钮将被检查,而其他按钮未被选中。无论您是否设置GroupName属性,该解决方案都能正常工作,尽管您通常应该设置它。

you can see the solution