Question

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();
  }
  }
Was it helpful?

Solution

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>

OTHER TIPS

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.

The odd part is that the type of the FallbackValue on the child binding is required to match the target of the MultiBinding. I don't understand this requirement, as the MultiBinding converter can take values from bindings that don't match that type.

With this in mind, the easiest workaround is to modify your MultiBinding's Converter to handle multiple types. 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:

    <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>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top