Alex141 / CalcBinding

Advanced WPF Binding which supports expressions in Path property and other features

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Custom types with defined implicit cast to bool are unsupported by BoolToVisibility converter

rstroilov opened this issue · comments

I faced in issue in my project. When using a type which has defined implicit cast to bool in a property, binding visibility to that property doesn't work and conversion fails with following message:
System.InvalidCastException: Specified cast is not valid.

It happens because of explicit cast is called on value in BoolToVisibilityConverter.Convert:
if ((bool)value) return Visibility.Visible;

this test reproduces issue:

        [Test]
        public void DoesNotFailConvertingWhenValueHasImplicitConversionToBool()
        {
            Assert.DoesNotThrow(() =>
                new BoolToVisibilityConverter()
                .Convert(new CastableToBoolean(true), typeof(Visibility), null, CultureInfo.CurrentCulture));
        }

        private sealed class CastableToBoolean
        {
            private bool value;

            public CastableToBoolean(bool value = false)
            {
                this.value = value;
            }

            public static implicit operator bool(CastableToBoolean obj)
            {
                return obj.value;
            }
        }

Hi,
I agree with problem, but disagree with solution. I think it can be made shorter and more clear. How about using DLR?

     public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
     {
       var boolValue = (value is bool) ? (bool)value : (bool)(dynamic)value;
       ...
     }

If we remove cast to bool after dynamic cast, we handle implicit operators. If we leave bool cast, we can handle both explicit and implicit operators. What do you say?

Hi Alex,

your solution looks nice and beautiful, much better than my, but, unfortunately, it doesn't work for case specified.

... : (bool)(dynamic)value will cause same InvalidCastException
... : (dynamic)value will cause RuntimeBinderException saying that there is no implicit cast between object and bool.

Hi Roman,

Ok, I compared yours and my examples. The difference is only in access modifier of CastableToBoolean. I use 'public class' and you use 'private class'. Because of privacy of the class dlr can't acess to implicit operator. Changing access modifier on 'public' solves this problem.

Hmm, because the sample class models the class being used as the type of the source property, it must be public, as well as the property itself, otherwise the binding will simply not work, this is a general requirement for all properties (https://docs.microsoft.com/en-us/dotnet/framework/wpf/data/binding-sources-overview#other-characteristics).

So the solution of this problem is in changing the access modifier of convertable class to public.

I was wondered and checked - yes, you are right. It looks a bit confusing, that access modifier is so important here, but it really works as it should.

Ok, I glad that we solved this problem by our efforts :) I will commit the changes and release a new version tomorrow

Version 2.3.0.1 with this fix has been released