diff --git a/CalcBinding/BoolToVisibilityConverter.cs b/CalcBinding/BoolToVisibilityConverter.cs index cf23b44..c829109 100644 --- a/CalcBinding/BoolToVisibilityConverter.cs +++ b/CalcBinding/BoolToVisibilityConverter.cs @@ -1,5 +1,8 @@ using System; +using System.Collections.Generic; using System.Globalization; +using System.Linq; +using System.Reflection; using System.Windows; using System.Windows.Data; @@ -22,6 +25,17 @@ public BoolToVisibilityConverter(FalseToVisibility falseToVisibility) public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { + var valueType = value.GetType(); + + if (valueType != typeof(bool)) + { + var implicitConverter = GetImplicitConversion(valueType, typeof(bool)); + if (implicitConverter != null) + { + value = implicitConverter.Invoke(null, new object[] { value }); + } + } + if ((bool)value) return Visibility.Visible; @@ -34,5 +48,25 @@ public object ConvertBack(object value, Type targetType, object parameter, Cultu } public FalseToVisibility FalseToVisibility { get; set; } + + private static MethodInfo GetImplicitConversion(Type baseType, Type targetType) + { + return GetAllImplicitCasts(baseType, targetType) + .FirstOrDefault(); + } + + private static IEnumerable GetAllImplicitCasts(Type baseType, Type targetType) + { + var currentTypeMethods = baseType.GetMethods(BindingFlags.Public | BindingFlags.Static) + .Where(x => x.Name == "op_Implicit" && x.ReturnType == targetType) + .ToList(); + + while (baseType != typeof(object) && !currentTypeMethods.Any()) + { + return GetAllImplicitCasts(baseType.BaseType, targetType); + } + + return currentTypeMethods; + } } } diff --git a/Tests/BoolToVisibilityConverterTests.cs b/Tests/BoolToVisibilityConverterTests.cs index a15b396..38e14f6 100644 --- a/Tests/BoolToVisibilityConverterTests.cs +++ b/Tests/BoolToVisibilityConverterTests.cs @@ -1,11 +1,6 @@ using CalcBinding; using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Windows; namespace Tests @@ -16,8 +11,6 @@ public class BoolToVisibilityConverterTests [TestMethod] public void ConvertBoolToVisibilityTest() { - var converter = new CalcConverter(); - Assert.AreEqual(Visibility.Visible, new BoolToVisibilityConverter() .Convert(true, typeof(Visibility), null, CultureInfo.CurrentCulture)); @@ -45,6 +38,37 @@ public void ConvertVisibilityToBoolTest() Assert.AreEqual(false, new BoolToVisibilityConverter() .ConvertBack(Visibility.Hidden, typeof(bool), null, CultureInfo.CurrentCulture)); - } + } + + [TestMethod] + public void ConvertsCastableToBoolWhenValueHasImplicitConversion() + { + Assert.AreEqual(Visibility.Visible, + new BoolToVisibilityConverter() + .Convert(new CastableToBoolean(true), typeof(Visibility), null, CultureInfo.CurrentCulture)); + + Assert.AreEqual(Visibility.Collapsed, + new BoolToVisibilityConverter() + .Convert(new CastableToBoolean(false), typeof(Visibility), null, CultureInfo.CurrentCulture)); + + Assert.AreEqual(Visibility.Hidden, + new BoolToVisibilityConverter(FalseToVisibility.Hidden) + .Convert(new CastableToBoolean(false), 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; + } + } } }