XAML Compiler: Will not compile custom IValueConverter

JohnHindJohnHind GBMember ✭✭

I have a fairly complex app that works fine until I try to compile the XAML. Three fairly simple XAML files in the app compile fine but the main XAML file gives the following 'helpful' error message:

Object reference not set to an instance of an object.

This is localised to the XAML file, but no localisation within the file.

Channelling my late 20th century self, I fired up the ancient debugging technique of commenting stuff out until the problem went away! The last line below is what causes the problem:

xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:JH.Core.Tools"
....
<local:SwitchConverter x:TypeArguments="Color" TrueValue="Red" FalseValue="Black" />

With the value converter defined in my JH.Core.Tools thusly:

    /// <summary>
    /// A generic two-state type converter for XAML. Specialise to the desired input and output types. TestValue is the
    /// input value converted to TrueValue, all other input values convert to FalseValue. TrueValue and FalseValue are ignored 
    /// if the output type is Bool. DefaultValue is only used in reverse conversions and is the input value returned when the
    /// output value converted back is other than TrueValue (assumed to be FalseValue). If DefaultValue is not set, the
    /// default for the input type is used.
    /// </summary>
    public class SwitchConverter<IN,OUT> :IValueConverter
    {
        public SwitchConverter() { TestValue = DefaultValue = default(IN); FalseValue = TrueValue = default(OUT); }
        /// <summary>
        /// Output returned when input matches TestValue or is bool true.
        /// </summary>
        public OUT TrueValue { set; get; }
        /// <summary>
        /// Output value returned when input does not match TestValue or is bool false.
        /// </summary>
        public OUT FalseValue { set; get; }
        /// <summary>
        /// The input value which is considered True for input types other than bool.
        /// </summary>
        public IN TestValue { set; get; }
        /// <summary>
        /// A value returned in place of the type default when a reverse conversion is applied and value converted is
        /// bool false or does not match TrueValue.
        /// </summary>
        public IN DefaultValue { set; get; }
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (targetType == typeof(bool))
                return (value.Equals(TestValue));
            else
                return (value.Equals(TestValue)) ? TrueValue : FalseValue;
        }
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value.GetType() == typeof(bool))
                return ((bool)value)? TestValue : DefaultValue;
            else
                return (value.Equals(TrueValue)) ? TestValue : DefaultValue;
        }
    }
    /// <summary>
    /// Short-cut for SwitchConverter with bool input type. No need to set TestValue or DefaultValue.
    /// </summary>
    public class SwitchConverter<OUT> : SwitchConverter<bool, OUT> { public SwitchConverter() { TestValue = true; DefaultValue = false; } }

Anyone have any pointers as to what may be going wrong, or how the hell I am supposed to diagnose it? I emphasise that this works fine with XAML compilation switched off.

Posts

  • JohnHindJohnHind GBMember ✭✭

    OK, weird! If I change it to avoid using the shortcut generic it works fine:

    <local:SwitchConverter x:TypeArguments="x:Boolean,Color" TrueValue="Red" FalseValue="Black" TestValue="True" />

    So it looks like a bug in the XAML compiler!

  • HunumanHunuman GBMember ✭✭✭✭

    Hi @JohnHind

    AFAIK defining the Converter in the App resources as follows should address the issue:

    <local:SwitchConverter x:Key="SwitchConverter" />

    Hope this help,

    Tim

  • JohnHindJohnHind GBMember ✭✭

    @Hunuman said:
    AFAIK defining the Converter in the App resources as follows should address the issue:

    Nope! I can define the SwitchConverter in resources:

    <local:SwitchConverter x:Key="SwitchConverter" x:TypeArguments="Color" TrueValue="Red" FalseValue="Black" />

    Then simplify the reference to:

    <Label Style="{StaticResource Status}" Text="{Binding Status}" TextColor="{Binding IsFault, Converter={StaticResource SwitchConverter} }"/>

    But then I still get an error message.

    If I expand the resources entry to:

    <local:SwitchConverter x:Key="SwitchConverter" x:TypeArguments="x:Boolean,Color" TrueValue="Red" FalseValue="Black" TestValue="true"/>

    It works fine.

    Definitely looks like the XAML compiler cannot cope with overloaded generics.

Sign In or Register to comment.