Search code examples
wpfbindingimultivalueconverter

WPF 3.5: MultiValueConverter Values are NamedObjects Where Single ValueConverters Work as per Normal


I'm having a problem with a MultiValueConverter that feels more and more like a .NET bug the more I try to fix it. Here's what's up:

I am binding the IsEnabled property of both a Stackpanel and a User Control (UC) using a similar MultiBinding definition (of course, I'm using <ns:usercontrolname.IsEnabled> for the UC):

<StackPanel.IsEnabled>
    <MultiBinding Converter="{StaticResource InfoSectionIsEnabled}">
        <Binding Path="IsInactive" />
        <Binding Path="IsWaitingForMicro" />
    </MultiBinding>
</StackPanel.IsEnabled>

The 'current' UC (the one containing this XAML) is being assigned to a TabItem.Content. The DataContext is set at the TabItem.

I'm also using the Properties above in two separate, single-value bindings on the same 'current' UC:

<scps:ucSOIA x:Name="ucSOIA" IsEnabled="{Binding Path=IsWaitingForMicro, Converter={StaticResource InvertBool}}"/>

and

<scps:ucMisc x:Name="ucMisc" IsEnabled="{Binding Path=IsInactive, Converter={StaticResource InvertBool}}"/>

All the bindings work fine when the 'current' UC is first instantiated and assigned to the TabItem's Content. But as soon as I change the TabItem's Content to a different UC (without disposing of the instantiated, 'current' UC), all converters are called again and the MultiValueConverter's values() parameter contains NamedObject for both entires. The single-value converters, using the exact same Properties, work fine.

I can't figure this out. I've even tried using RelativeSource on the MultiBindings, to no avail.

I've got two questions:

  1. How can the values in the MultiBindingConverter be NamedObject when the single-value bindings work fine

  2. The less-important question is why are the bindings being called when I change the TabItem's Content (note, these converters are being called prior to UserControl.Unloaded)

Thanks, Dave


Solution

  • Worked it out, to an extent at least. You need to be more robust with your multibinding converter (InfoSectionIsEnabled).

    In my case, my converter was as follows:

    Public Function Convert(values() As Object,
                            targetType As System.Type,
                            parameter As Object,
                            culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IMultiValueConverter.Convert
        If values IsNot Nothing Then
            Return values.All(Function(n) CBool(n))
        End If
        Return False
    End Function
    

    I then spotted in another post (lost the link already, sorry) that at design time, because the IDE cannot evaluate the correct values to pass to the converter, it passes a 'NamedObject' for each of the bindings.

    In my case, I was only concerned with Booleans, so I changed my code to specifically deal with those cases only (thereby preventing accidentally attempting to cast the NamedObjects to boolean):

    Public Function Convert(values() As Object,
                            targetType As System.Type,
                            parameter As Object,
                            culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IMultiValueConverter.Convert
        If values IsNot Nothing AndAlso values.All(Function(n) TypeOf n Is Boolean) Then
            Return values.All(Function(n) CBool(n))
        End If
        Return False
    End Function
    

    This immediately resolved the issue for me.