Handling a bool fallback value for a binding within a MultiBinding

justin peterson picture justin peterson · Jan 9, 2013 · Viewed 9.3k times · Source

I have a MultiBinding converter that determines the visibility of a control depending on if both of my Binding fields evaluate to true. If for some reason it can't reach either of these bool properties, I want to set them to evaluate to 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:

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. 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? 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();
  }
  }

Answer

Metro Smurf picture Metro Smurf · Jan 9, 2013

The FallbackValue value should be the Visibility value to fallback on when the binding fails:

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

EDIT

From the FallbackValue documentation:

fallbackValue
An attribute or object element value of the same type as the target property. See that type's documentation for XAML usage information. 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.

In this case, the target property of the MultiBinding is the Visibility property. Even though the value of the child MultiBinding properties is expecting a bool, the parent MultiBinding is expecting a Visiblity value from the binding. This means the FallbackValue for each of the MultiBinding properties should have a FallbackValue for the Visibility property.

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. 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 Converter="{StaticResource AndToVisibilityConverter1}" FallbackValue="Visible">
    <Binding Path="IsConnected" />
    <Binding Path="CurrentUser.IsConsumerOnlyAgent" Converter="{StaticResource InvertedBooleanConverter1}" />
</MultiBinding>