WPF MultiBinding VS designer exception

2019-08-09 10:29发布

问题:

Visual Studio 2010 designer says that unhandled exception occurred in MultiValueConverter but I can build my program and it works fine (multibinding also works).

XAML (I set window.DataContext in constructor):

            <ComboBox Name="cbbProfile" DisplayMemberPath="Name" Grid.Row="1" Margin="10,5" Grid.ColumnSpan="3" ItemsSource="{Binding ProfilesData.ProfilesItems}" SelectionChanged="cbbProfile_SelectionChanged" >
                <ComboBox.IsEnabled>
                    <MultiBinding Converter="{StaticResource multiEnabledToEnabled}">
                        <Binding Path="ProfilesData.ProfilesItems.Count" Converter="{StaticResource itemsCountToEnabled}" />
                        <Binding Path="State" Converter="{StaticResource stateToControlsEnabled}" />
                    </MultiBinding>
                </ComboBox.IsEnabled>
            </ComboBox>

Converters:

public class MultiEnabledToEnabled : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    { 
        foreach (object val in values)
        {
            if (!(bool) val)     // <-- EXCEPTION (line 176) HERE 
                return false;
        } 

        return true;
    }    

public class ItemsCountToEnabled : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (int)value == 0 ? false : true;
    }

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

public class StateToControlsEnabled : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var val = (ProgramState)value;
        switch (val)
        {
            ...
            default:
                return true;
        }

    }

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

VS Exception text:

System.InvalidCastException Specified cast is not valid. at myassemblyname.MultiEnabledToEnabled.Convert(Object[] values, Type targetType, Object parameter, CultureInfo culture) in C:...\Converters.cs:line 176 at System.Windows.Data.MultiBindingExpression.TransferValue() at System.Windows.Data.MultiBindingExpression.Transfer() at System.Windows.Data.MultiBindingExpression.UpdateTarget(Boolean includeInnerBindings) at System.Windows.Data.MultiBindingExpression.AttachToContext(Boolean lastChance) at System.Windows.Data.MultiBindingExpression.MS.Internal.Data.IDataBindEngineClient.AttachToContext(Boolean lastChance) at MS.Internal.Data.DataBindEngine.Task.Run(Boolean lastChance) at MS.Internal.Data.DataBindEngine.Run(Object arg) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)

回答1:

My best guess is that the binding happens before some initialization, and at least one value in the collection of object is DependencyProperty.UnsetValue, making the cast invalid.

Now, assuming you have a design time viewmodel set up, you could check beforehand if all the values are indeed booleans:

if(values.All(v => v is bool))
{
   //Do regular computation
}
else
{
   //Handle edge case
}

But as soon as any view gets complicated, the designer breaks, and it is painful to get it working again.

Expression Blend handles this better, if you absolutely want a designer but can't be bothered to set up a design time environment, go for it.

Otherwise do it like most people: forget about the designer.



回答2:

VS designer is a hard beast to work with and I've come to conclusion that it is not worth the effort. But you can use:

if(DesignerProperties.GetIsInDesignMode(Application.MainWindow))

To provide default value for your converter. This will remover the error.

DesignerProperties.GetIsInDesignMode method at msdn