简体   繁体   English

处理MultiBinding中绑定的bool后备值

[英]Handling a bool fallback value for a binding within a MultiBinding

I have a MultiBinding converter that determines the visibility of a control depending on if both of my Binding fields evaluate to true. 我有一个MultiBinding转换器,它根据我的两个Binding字段是否评估为true来确定控件的可见性。 If for some reason it can't reach either of these bool properties, I want to set them to evaluate to true. 如果由于某种原因它无法达到这些bool属性中的任何一个,我想将它们设置为true。 For example: 例如:

The code that I currently have is: 我目前拥有的代码是:

           <MultiBinding Converter="{StaticResource AndToVisibilityConverter1}" FallbackValue="Visible">
              <Binding Path="IsConnected" FallbackValue="true" />
              <Binding Path="CurrentUser.IsConsumerOnlyAgent" Converter="{StaticResource InvertedBooleanConverter1}" FallbackValue="True" />
           </MultiBinding>

The code runs fine, however I get the error message in my IDE's output that indicates: 代码运行正常,但我在IDE的输出中收到错误消息,指出:

System.Windows.Data Error: 11 : Fallback value 'True' (type 'String') cannot be converted for use in 'Visibility' (type 'Visibility'). BindingExpression:Path=IsConnected; DataItem=null; target element is 'StackPanel' (Name=''); 

Which I've pinpointed to this converter and verified it is where the XAML error is. 我已经确定了这个转换器并验证了它是XAML错误的位置。 Sorry for the ignorance here, but is there a way to possibly set the FallbackValue to each of these bindings to evaluate to "true" upon failure to obtain the set path? 对于这里的无知感到抱歉,但有没有办法可以将FallbackValue设置为这些绑定中的每一个,以便在未能获得设置路径时评估为“true”? Thanks in advance 提前致谢

Update: 更新:

Here's the code for my Visibility Converter (I use this in several places throughout my app, just want to add fallback values): 这是我的可见性转换器的代码(我在我的应用程序的几个地方使用它,只想添加回退值):

   internal class AndToVisibilityConverter : IMultiValueConverter
  {
  public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
  {
     if (values == null)
        return Visibility.Collapsed;

     foreach (var value in values)
     {
        if (value == null || !(value is bool))
           return Visibility.Collapsed;

        if (!((bool) value))
           return Visibility.Collapsed;
     }

     return Visibility.Visible;
  }

  public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
  {
     throw new NotImplementedException();
  }
  }

The FallbackValue value should be the Visibility value to fallback on when the binding fails: FallbackValue值应该是绑定失败时要回退的Visibility值:

<Binding Path="CurrentUser.IsConsumerOnlyAgent" 
    Converter="{StaticResource InvertedBooleanConverter1}" 
                FallbackValue="Visible" />

EDIT 编辑

From the FallbackValue documentation : FallbackValue文档

fallbackValue fallbackValue
An attribute or object element value of the same type as the target property. 与目标属性相同类型的属性或对象元素值。 See that type's documentation for XAML usage information. 请参阅该类型的XAML用法信息文档。 That type may or may not support attribute syntax for its values, or may or may not support object element syntax (which requires a default constructor on that type). 该类型可能支持或不支持其值的属性语法,或者可能支持或不支持对象元素语法(这需要该类型的默认构造函数)。 The target property type will therefore influence which syntax you use for the value of the FallbackValue property. 因此,目标属性类型将影响您用于FallbackValue属性值的语法。

In this case, the target property of the MultiBinding is the Visibility property. 在这种情况下,MultiBinding的target属性是Visibility属性。 Even though the value of the child MultiBinding properties is expecting a bool, the parent MultiBinding is expecting a Visiblity value from the binding. 尽管子MultiBinding属性的值期望bool,但父MultiBinding期望绑定的Visiblity值。 This means the FallbackValue for each of the MultiBinding properties should have a FallbackValue for the Visibility property. 这意味着每个MultiBinding属性的FallbackValue应具有Visibility属性的FallbackValue。

Seems a bit counter-intuitive, but does make sense when thought through (IMO), re: if there was not a converter on the MultiBindng, then the return values of the binding should be a Visibility value. 看起来有点违反直觉,但在考虑(IMO)时确实有意义,重新:如果MultiBindng上没有转换器,那么绑定的返回值应该是Visibility值。 Remove the converter from the equation and it may help to clear things up. 从等式中删除转换器,它可能有助于清理。

For your case, skip the FallbackValue for each of the MultiBinding values and set the FallbackValue on the MultiBinding as you have now. 对于您的情况,跳过每个MultiBinding值的FallbackValue,并像现在一样在MultiBinding上设置FallbackValue。

<MultiBinding Converter="{StaticResource AndToVisibilityConverter1}" FallbackValue="Visible">
    <Binding Path="IsConnected" />
    <Binding Path="CurrentUser.IsConsumerOnlyAgent" Converter="{StaticResource InvertedBooleanConverter1}" />
</MultiBinding>

After some testing, it seems that when a "child binding" in a MultiBinding fails (due to UnsetValue or failure to find bound property) the child binding's FallbackValues get passed into the Converter on the MultiBinding. 经过一些测试,似乎当MultiBinding中的“子绑定”失败时(由于UnsetValue或找不到绑定属性),子绑定的FallbackValues会传递到MultiBinding上的Converter中。

The odd part is that the type of the FallbackValue on the child binding is required to match the target of the MultiBinding . 奇怪的是, 子绑定上的FallbackValue的类型需要与MultiBinding的目标匹配。 I don't understand this requirement, as the MultiBinding converter can take values from bindings that don't match that type. 我不明白这个要求,因为MultiBinding转换器可以从与该类型不匹配的绑定中获取值。

With this in mind, the easiest workaround is to modify your MultiBinding's Converter to handle multiple types. 考虑到这一点,最简单的解决方法是修改MultiBinding的Converter以处理多种类型。 In this case, it would need to handle boolean and Visibility. 在这种情况下,它需要处理布尔值和可见性。

ie, my convert function looks like this: 即,我的转换函数看起来像这样:

    public object Convert( object[] values, Type targetType, object     parameter, System.Globalization.CultureInfo culture )
    {
        var bools = values.Where( b => b is bool ).Cast<bool>();
        var vis = values.Where( v => v is Visibility ).Cast<Visibility>();

        // if no usable values, return unset
        if( vis.Count() + bools.Count() == 0 )
            return DependencyProperty.UnsetValue;

        // if true, return visible
        if( bools.All( b => b ) && vis.All( v => v == Visibility.Visible ) )
            return Visibility.Visible;

        // if false, see if hidden or collapsed is specified
        var param = parameter as string;

        Visibility ret;
        if( Enum.TryParse( param, out ret ) )
            return ret;

        // default to collapsed
        return Visibility.Collapsed;
    }

This workaround should provide the behavior requested by specifying Visible for true and something else for false: 此解决方法应通过将true指定为true而将其他指定为false来提供所请求的行为:

    <MultiBinding Converter="{x:Static con:MultiAndToVisibilityConverter.Instance}">
        <Binding Path="IsChecked" ElementName="CheckButton"/>
        <Binding Path="RadioOne.IsChecked" FallbackValue="{x:Static Visibility.Visible}"
                 Converter="{x:Static con:BoolInverterConverter.Instance}"/>
    </MultiBinding>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM