diff --git a/samples/Directory.Packages.props b/samples/Directory.Packages.props
index f9ffa7fe2..ba0413bd0 100644
--- a/samples/Directory.Packages.props
+++ b/samples/Directory.Packages.props
@@ -23,25 +23,25 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/samples/Uno.Toolkit.Samples/Uno.Toolkit.Samples.Shared/Content/Helpers/ResponsiveExtensionsSamplePage.xaml b/samples/Uno.Toolkit.Samples/Uno.Toolkit.Samples.Shared/Content/Helpers/ResponsiveExtensionsSamplePage.xaml
index 7e8775f70..b14ac5ba2 100644
--- a/samples/Uno.Toolkit.Samples/Uno.Toolkit.Samples.Shared/Content/Helpers/ResponsiveExtensionsSamplePage.xaml
+++ b/samples/Uno.Toolkit.Samples/Uno.Toolkit.Samples.Shared/Content/Helpers/ResponsiveExtensionsSamplePage.xaml
@@ -15,6 +15,15 @@
+
+
+
+
+
+
+
+
+
@@ -22,12 +31,7 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props
index 584279618..a8e107bea 100644
--- a/src/Directory.Packages.props
+++ b/src/Directory.Packages.props
@@ -15,23 +15,23 @@
-
-
-
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
+
diff --git a/src/Uno.Toolkit.RuntimeTests/Tests/DependencyObjectExtensionTests.cs b/src/Uno.Toolkit.RuntimeTests/Tests/DependencyObjectExtensionTests.cs
new file mode 100644
index 000000000..4bc72615c
--- /dev/null
+++ b/src/Uno.Toolkit.RuntimeTests/Tests/DependencyObjectExtensionTests.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Uno.Toolkit.UI;
+using Uno.UI.RuntimeTests;
+
+#if IS_WINUI
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+#else
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+#endif
+
+namespace Uno.Toolkit.RuntimeTests.Tests;
+
+[TestClass]
+[RunsOnUIThread]
+internal class DependencyObjectExtensionTests
+{
+ [TestMethod]
+ public void When_Type_FindDependencyProperty()
+ {
+ var dp = typeof(Grid).FindDependencyProperty(nameof(Grid.PaddingProperty));
+
+ Assert.AreEqual(Grid.PaddingProperty, dp);
+ }
+
+ [TestMethod]
+ public void When_Type_FindDependencyProperty_Attached()
+ {
+ var dp = typeof(Grid).FindDependencyProperty(nameof(Grid.RowProperty));
+
+ Assert.AreEqual(Grid.RowProperty, dp);
+ }
+
+ [TestMethod]
+ public void When_DO_FindDependencyProperty()
+ {
+ var dp = new Grid().FindDependencyProperty(nameof(Grid.PaddingProperty));
+
+ Assert.AreEqual(Grid.PaddingProperty, dp);
+ }
+
+ [TestMethod]
+ public void When_DO_FindDependencyProperty_Attached()
+ {
+ var dp = new Grid().FindDependencyProperty(nameof(Grid.RowProperty));
+
+ Assert.AreEqual(Grid.RowProperty, dp);
+ }
+}
diff --git a/src/Uno.Toolkit.Skia.WinUI/Controls/Shadows/ShadowContainer.cs b/src/Uno.Toolkit.Skia.WinUI/Controls/Shadows/ShadowContainer.cs
index abf901ba4..ebea428e6 100644
--- a/src/Uno.Toolkit.Skia.WinUI/Controls/Shadows/ShadowContainer.cs
+++ b/src/Uno.Toolkit.Skia.WinUI/Controls/Shadows/ShadowContainer.cs
@@ -376,7 +376,7 @@ private void InvalidateShadows(bool force = false)
StackPanel => StackPanel.CornerRadiusProperty,
Shape => null, // note: shapes have special handling, see: GetShadowShapeContext
- DependencyObject @do => @do.FindDependencyPropertyUsingReflection("CornerRadiusProperty"),
+ DependencyObject @do => @do.FindDependencyProperty("CornerRadiusProperty"),
_ => null,
};
}
@@ -392,7 +392,7 @@ private void InvalidateShadows(bool force = false)
StackPanel stackpanel => stackpanel.CornerRadius,
Shape => null, // note: shapes have special handling, see: GetShadowShapeContext
- DependencyObject @do => @do.FindDependencyPropertyUsingReflection("CornerRadiusProperty") is { } dp
+ DependencyObject @do => @do.FindDependencyProperty("CornerRadiusProperty") is { } dp
? (CornerRadius)@do.GetValue(dp)
: null,
_ => null,
diff --git a/src/Uno.Toolkit.UI/Extensions/DependencyObjectExtensions.cs b/src/Uno.Toolkit.UI/Extensions/DependencyObjectExtensions.cs
index 522fd1ebd..b6ef2f0df 100644
--- a/src/Uno.Toolkit.UI/Extensions/DependencyObjectExtensions.cs
+++ b/src/Uno.Toolkit.UI/Extensions/DependencyObjectExtensions.cs
@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Reflection;
using Uno.Disposables;
using Uno.Extensions;
-using System.Reflection;
using Microsoft.Extensions.Logging;
using Uno.Logging;
@@ -25,7 +25,7 @@ namespace Uno.Toolkit.UI
{
internal static class DependencyObjectExtensions
{
- private static Dictionary<(Type type, string property), DependencyProperty?> _dependencyPropertyReflectionCache = new Dictionary<(Type, string), DependencyProperty?>(2);
+ private static Dictionary<(Type Type, string Property), DependencyProperty?> _dependencyPropertyReflectionCache = new Dictionary<(Type, string), DependencyProperty?>(2);
#if HAS_UNO
///
@@ -182,65 +182,55 @@ internal static void SetParent(this DependencyObject dependencyObject, object? p
}
#endif
- public static DependencyProperty? FindDependencyPropertyUsingReflection(this DependencyObject dependencyObject, string propertyName)
- {
- var type = dependencyObject.GetType();
- var propertyType = typeof(TProperty);
- var key = (ownerType: type, propertyName);
+ public static DependencyProperty? FindDependencyProperty(this DependencyObject owner, string propertyName) => owner.GetType().FindDependencyProperty(propertyName);
- if (_dependencyPropertyReflectionCache.TryGetValue(key, out var property))
- {
- return property;
- }
+ public static DependencyProperty? FindDependencyProperty(this DependencyObject owner, string propertyName) => owner.GetType().FindDependencyProperty(propertyName);
- property =
- type.GetProperty(propertyName, Public | Static | FlattenHierarchy)?.GetValue(null) as DependencyProperty ??
- type.GetField(propertyName, Public | Static | FlattenHierarchy)?.GetValue(null) as DependencyProperty;
+ public static DependencyProperty? FindDependencyProperty(this Type ownerOrDescendantType, string propertyName)
+ {
+ var propertyType = typeof(TProperty);
+ var property = FindDependencyProperty(ownerOrDescendantType, propertyName);
#if HAS_UNO
- if (property == null)
- {
- typeof(DependencyObjectExtensions).Log().LogWarning($"The '{type}.{propertyName}' dependency property does not exist.");
- }
- else if (property.GetType() != propertyType)
+ // note: for winui, it is no possible to obtain the property type from DependencyProperty by reflection.
+ // we can only check the sibling {propertyName} property or G/Set{propertyName} method (for attached dp) for the property type.
+ if (property != null && (
+ property.GetType().GetProperty("Type", NonPublic | Instance)?.GetValue(property) is not Type type ||
+ type != propertyType
+ ))
{
- typeof(DependencyObjectExtensions).Log().LogWarning($"The '{type}.{propertyName}' dependency property is not of the expected '{propertyType}' type.");
+ typeof(DependencyObjectExtensions).Log().LogWarning($"The '{ownerOrDescendantType.GetType().Name}.{propertyName}' dependency property is not of the expected '{propertyType.Name}' type.");
property = null;
}
#endif
- _dependencyPropertyReflectionCache[key] = property;
-
return property;
}
- public static DependencyProperty? FindDependencyPropertyUsingReflection(this DependencyObject dependencyObject, string propertyName)
+ public static DependencyProperty? FindDependencyProperty(this Type ownerOrDescendantType, string propertyName)
{
- var type = dependencyObject.GetType();
+ var type = ownerOrDescendantType;
var key = (ownerType: type, propertyName);
- if (_dependencyPropertyReflectionCache.TryGetValue(key, out var property))
+ // given that we are doing FlattenHierarchy lookup, it is fine that we are storing multiple pairs of (types-to-same-dp)
+ // since it is not worth the trouble to handle the type hierarchy...
+ if (!_dependencyPropertyReflectionCache.TryGetValue(key, out var property))
{
- return property;
+ property =
+ type.GetProperty(propertyName, Public | Static | FlattenHierarchy)?.GetValue(null) as DependencyProperty ??
+ type.GetField(propertyName, Public | Static | FlattenHierarchy)?.GetValue(null) as DependencyProperty;
+ _dependencyPropertyReflectionCache[key] = property;
}
- property =
- type.GetProperty(propertyName, Public | Static | FlattenHierarchy)?.GetValue(null) as DependencyProperty ??
- type.GetField(propertyName, Public | Static | FlattenHierarchy)?.GetValue(null) as DependencyProperty;
-
-#if HAS_UNO
if (property == null)
{
- typeof(DependencyObjectExtensions).Log().LogWarning($"The '{type}.{propertyName}' dependency property does not exist.");
+ typeof(DependencyObjectExtensions).Log().LogWarning($"The dependency property '{propertyName}' does not exist on '{type}' or its ancestors.");
}
-#endif
-
- _dependencyPropertyReflectionCache[key] = property;
return property;
}
- public static bool TryGetValue(this DependencyObject dependencyObject, DependencyProperty dependencyProperty, out DependencyObject? value)
+ private static bool TryGetValue(this DependencyObject dependencyObject, DependencyProperty dependencyProperty, out DependencyObject? value)
{
value = default;
diff --git a/src/Uno.Toolkit.UI/Helpers/PaddingHelper.cs b/src/Uno.Toolkit.UI/Helpers/PaddingHelper.cs
index fbe76aab1..4cbab847d 100644
--- a/src/Uno.Toolkit.UI/Helpers/PaddingHelper.cs
+++ b/src/Uno.Toolkit.UI/Helpers/PaddingHelper.cs
@@ -23,7 +23,7 @@ public static Thickness GetPadding(UIElement uiElement)
return padding;
}
- var property = uiElement.FindDependencyPropertyUsingReflection("PaddingProperty");
+ var property = uiElement.FindDependencyProperty("PaddingProperty");
return property != null && uiElement.GetValue(property) is Thickness t ? t : default;
}
@@ -35,7 +35,7 @@ public static bool SetPadding(UIElement uiElement, Thickness padding)
return true;
}
- var property = uiElement.FindDependencyPropertyUsingReflection("PaddingProperty");
+ var property = uiElement.FindDependencyProperty("PaddingProperty");
if (property != null)
{
uiElement.SetValue(property, padding);
@@ -53,7 +53,7 @@ public static bool TryUpdatePadding(this FrameworkElement frameworkElement, Thic
return !padding.Equals(newPadding) && TrySetPadding(frameworkElement, newPadding);
}
- var property = frameworkElement.FindDependencyPropertyUsingReflection("PaddingProperty");
+ var property = frameworkElement.FindDependencyProperty("PaddingProperty");
if (property is { } && frameworkElement.GetValue(property) is Thickness currentPadding)
{
if (!currentPadding.Equals(newPadding))
diff --git a/src/Uno.Toolkit.UI/Markup/ResponsiveExtension.cs b/src/Uno.Toolkit.UI/Markup/ResponsiveExtension.cs
index 7fd09330a..c2228cee9 100644
--- a/src/Uno.Toolkit.UI/Markup/ResponsiveExtension.cs
+++ b/src/Uno.Toolkit.UI/Markup/ResponsiveExtension.cs
@@ -4,14 +4,11 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.Logging;
using Windows.Foundation;
using Uno.Extensions;
using Uno.Logging;
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
-
-
#if IS_WINUI
using Microsoft.UI.Xaml;
@@ -85,21 +82,16 @@ private void BindToEvents(IXamlServiceProvider serviceProvider)
if (serviceProvider.GetService(typeof(IProvideValueTarget)) is IProvideValueTarget pvt &&
pvt.TargetObject is FrameworkElement target &&
pvt.TargetProperty is ProvideValueTargetProperty pvtp &&
- target.FindDependencyPropertyUsingReflection($"{pvtp.Name}Property") is DependencyProperty dp)
+ pvtp.DeclaringType.FindDependencyProperty($"{pvtp.Name}Property") is DependencyProperty dp)
{
TargetWeakRef = new WeakReference(target);
_targetProperty = dp;
- _propertyType =
-#if HAS_UNO // workaround for uno#14719: uno doesn't inject the proper pvtp.Type
- typeof(DependencyProperty).GetProperty("Type", Instance | NonPublic)?.GetValue(dp) as Type;
-#else
- pvtp.Type;
-#endif
+ _propertyType = pvtp.Type;
+
// here, we need to bind to two events:
// 1. Window.SizeChanged for obvious reason
// 2. Control.Loaded because the initial value(result of ProvideValue) is resolved without the inherited .resources
// which may define a different DefaultResponsiveLayout resource somewhere along the visual tree, so we need to rectify that.
-
ResponsiveHelper.GetForCurrentView().Register(this);
target.Loaded += OnTargetLoaded;
@@ -158,7 +150,7 @@ private void UpdateBindingIfNeeded(ResponsiveHelper? helper = null, bool forceAp
var helper = ResponsiveHelper.GetForCurrentView();
var resolved = helper.ResolveLayout(GetAppliedLayout(), GetAvailableLayoutOptions());
var value = GetValueFor(resolved.Result);
-
+
CurrentValue = value;
CurrentLayout = resolved.Result;
LastResolved = resolved;
diff --git a/src/Uno.Toolkit.UITest/Controls/ShadowContainer/Given_ShadowContainer.cs b/src/Uno.Toolkit.UITest/Controls/ShadowContainer/Given_ShadowContainer.cs
index 638af9e44..34cb655f2 100644
--- a/src/Uno.Toolkit.UITest/Controls/ShadowContainer/Given_ShadowContainer.cs
+++ b/src/Uno.Toolkit.UITest/Controls/ShadowContainer/Given_ShadowContainer.cs
@@ -22,7 +22,6 @@ public class Given_ShadowContainer : TestBase
[Test]
[TestCase(10, 10, false)]
- [TestCase(10, 10, false)]
[TestCase(10, 10, true)]
[TestCase(-10, -10, false)]
[TestCase(-10, -10, true)]
@@ -30,6 +29,8 @@ public class Given_ShadowContainer : TestBase
[TestCase(10, -10, true)]
[TestCase(-10, 10, false)]
[TestCase(10, -10, false)]
+ //TODO: Re-enable when Android no longer crashes: https://github.com/unoplatform/uno.toolkit.ui/issues/982
+ [ActivePlatforms(Platform.Browser, Platform.iOS)]
public void When_Shadows(int xOffset, int yOffset, bool inner)
{
@@ -64,7 +65,6 @@ public void When_Shadows(int xOffset, int yOffset, bool inner)
[Test]
[TestCase(10, 10, false)]
- [TestCase(10, 10, false)]
[TestCase(10, 10, true)]
[TestCase(-10, -10, false)]
[TestCase(-10, -10, true)]
@@ -72,6 +72,8 @@ public void When_Shadows(int xOffset, int yOffset, bool inner)
[TestCase(10, -10, true)]
[TestCase(-10, 10, false)]
[TestCase(10, -10, false)]
+ //TODO: Re-enable when Android no longer crashes: https://github.com/unoplatform/uno.toolkit.ui/issues/982
+ [ActivePlatforms(Platform.Browser, Platform.iOS)]
public void When_RectangleShadows(int xOffset, int yOffset, bool inner)
{
@@ -106,6 +108,8 @@ public void When_RectangleShadows(int xOffset, int yOffset, bool inner)
[Test]
[TestCase(10, 10, false)]
[TestCase(-10, -10, false)]
+ //TODO: Re-enable when Android no longer crashes: https://github.com/unoplatform/uno.toolkit.ui/issues/982
+ [ActivePlatforms(Platform.Browser, Platform.iOS)]
public void When_AsymmetricShadowsCorner(int xOffset, int yOffset, bool inner)
{
var shadowContainer = App.WaitForElementWithMessage("shadowContainer");