浏览代码

Merge branch 'master' into fix-keybindings-foreach-crash

Max Katz 4 年之前
父节点
当前提交
2d10536abf

+ 1 - 1
src/Avalonia.Styling/Styling/Activators/PropertyEqualsActivator.cs

@@ -33,6 +33,6 @@ namespace Avalonia.Styling.Activators
 
 
         void IObserver<object>.OnCompleted() { }
         void IObserver<object>.OnCompleted() { }
         void IObserver<object>.OnError(Exception error) { }
         void IObserver<object>.OnError(Exception error) { }
-        void IObserver<object>.OnNext(object value) => PublishNext(Equals(value, _value));
+        void IObserver<object>.OnNext(object value) => PublishNext(PropertyEqualsSelector.Compare(_property.PropertyType, value, _value));
     }
     }
 }
 }

+ 30 - 2
src/Avalonia.Styling/Styling/PropertyEqualsSelector.cs

@@ -1,4 +1,6 @@
 using System;
 using System;
+using System.ComponentModel;
+using System.Globalization;
 using System.Text;
 using System.Text;
 using Avalonia.Styling.Activators;
 using Avalonia.Styling.Activators;
 
 
@@ -75,11 +77,37 @@ namespace Avalonia.Styling
             }
             }
             else
             else
             {
             {
-                var result = (control.GetValue(_property) ?? string.Empty).Equals(_value);
-                return result ? SelectorMatch.AlwaysThisInstance : SelectorMatch.NeverThisInstance;
+                return Compare(_property.PropertyType, control.GetValue(_property), _value)
+                    ? SelectorMatch.AlwaysThisInstance
+                    : SelectorMatch.NeverThisInstance;
             }
             }
+            
         }
         }
 
 
         protected override Selector? MovePrevious() => _previous;
         protected override Selector? MovePrevious() => _previous;
+
+        internal static bool Compare(Type propertyType, object propertyValue, object? value)
+        {
+            if (propertyType == typeof(object) &&
+                propertyValue?.GetType() is Type inferredType)
+            {
+                propertyType = inferredType;
+            }
+
+            var valueType = value?.GetType();
+
+            if (valueType is null || propertyType.IsAssignableFrom(valueType))
+            {
+                return Equals(propertyValue, value);
+            }
+
+            var converter = TypeDescriptor.GetConverter(propertyType);
+            if (converter?.CanConvertFrom(valueType) == true)
+            {
+                return Equals(propertyValue, converter.ConvertFrom(null, CultureInfo.InvariantCulture, value));
+            }
+
+            return false;
+        }
     }
     }
 }
 }

+ 23 - 0
tests/Avalonia.Styling.UnitTests/SelectorTests_PropertyEquals.cs

@@ -22,6 +22,23 @@ namespace Avalonia.Styling.UnitTests
             Assert.False(await activator.Take(1));
             Assert.False(await activator.Take(1));
         }
         }
 
 
+        [Theory]
+        [InlineData("Bar", FooBar.Bar)]
+        [InlineData("352", 352)]
+        [InlineData("0.1", 0.1)]
+        public async Task PropertyEquals_Matches_When_Property_Has_Matching_Value_And_Different_Type(string literal, object value)
+        {
+            var control = new TextBlock();
+            var target = default(Selector).PropertyEquals(TextBlock.TagProperty, literal);
+            var activator = target.Match(control).Activator.ToObservable();
+
+            Assert.False(await activator.Take(1));
+            control.Tag = value;
+            Assert.True(await activator.Take(1));
+            control.Tag = null;
+            Assert.False(await activator.Take(1));
+        }
+
         [Fact]
         [Fact]
         public void OfType_PropertyEquals_Doesnt_Match_Control_Of_Wrong_Type()
         public void OfType_PropertyEquals_Doesnt_Match_Control_Of_Wrong_Type()
         {
         {
@@ -40,5 +57,11 @@ namespace Avalonia.Styling.UnitTests
 
 
             Assert.Equal("TextBlock[Text=foo]", target.ToString());
             Assert.Equal("TextBlock[Text=foo]", target.ToString());
         }
         }
+
+        private enum FooBar
+        {
+            Foo,
+            Bar
+        }
     }
     }
 }
 }