Skip to content

Commit

Permalink
feat: automatic type conversion for res-markup
Browse files Browse the repository at this point in the history
  • Loading branch information
Xiaoy312 committed Dec 6, 2023
1 parent dbcce47 commit 11e8909
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,18 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:sample="using:Uno.Toolkit.Samples"
xmlns:utu="using:Uno.Toolkit.UI"
xmlns:void="used for commenting out node or attribute"
xmlns:void="used for quickly commenting out node or attribute"
mc:Ignorable="d void"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

<Page.Resources>
<Orientation x:Key="NarrowOrientation">Vertical</Orientation>
<Orientation x:Key="WideOrientation">Horizontal</Orientation>
<x:Double x:Key="NarrowFontSize">15</x:Double>
<x:Double x:Key="WideFontSize">25</x:Double>
<SolidColorBrush x:Key="NarrowRed">Crimson</SolidColorBrush>
<SolidColorBrush x:Key="WideBlue">Blue</SolidColorBrush>
</Page.Resources>

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<sample:SamplePageLayout IsDesignAgnostic="True">
<sample:SamplePageLayout.DesignAgnosticTemplate>
<DataTemplate>
<StackPanel Spacing="20">

<TextBlock Text="Orientation test | Normal=Vertical | Wide=Horizontal" FontWeight="Bold" />
<StackPanel Orientation="{utu:Responsive Normal={StaticResource NarrowOrientation}, Wide={StaticResource WideOrientation}}">
<StackPanel Orientation="{utu:Responsive Normal=Vertical, Wide=Horizontal}">
<TextBlock Text="A" />
<TextBlock Text="B" />
<TextBlock Text="C" />
Expand All @@ -35,14 +26,14 @@
<TextBlock Text="{utu:Responsive Narrow='Narrow Threshold 300', Normal='Normal Threshold 600', Wide='Wide Threshold 800'}" />

<TextBlock Text="FontSize test" FontWeight="Bold" />
<TextBlock Text="Normal 15 Wide 25" FontSize="{utu:Responsive Normal={StaticResource NarrowFontSize}, Wide={StaticResource WideFontSize}}" />
<TextBlock Text="Normal 15 Wide 25" FontSize="{utu:Responsive Normal=15, Wide=25}" />

<TextBlock Text="Color test | Normal Red | Wide Blue" FontWeight="Bold" />
<Border Width="30"
Height="30"
HorizontalAlignment="Left"
Background="{utu:Responsive Normal={StaticResource NarrowRed},
Wide={StaticResource WideBlue}}" />
Background="{utu:Responsive Normal=Red,
Wide=Blue}" />

<TextBlock Text="Custom values override" FontWeight="Bold" />
<StackPanel>
Expand Down
48 changes: 43 additions & 5 deletions src/Uno.Toolkit.UI/Markup/ResponsiveExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Logging;
using Windows.Foundation;
using Uno.Extensions;
using Uno.Logging;
using Windows.Foundation;

#if IS_WINUI
using Microsoft.UI.Xaml;
Expand All @@ -17,6 +18,8 @@
using Windows.UI.Xaml.Markup;
#endif

using static System.Reflection.BindingFlags;

namespace Uno.Toolkit.UI;

#if DEBUG
Expand All @@ -32,6 +35,8 @@ namespace Uno.Toolkit.UI;
/// </summary>
public partial class ResponsiveExtension : MarkupExtension, IResponsiveCallback
{
private static readonly ILogger _logger = typeof(ResponsiveExtension).Log();

public object? Narrowest { get; set; }
public object? Narrow { get; set; }
public object? Normal { get; set; }
Expand All @@ -42,6 +47,7 @@ public partial class ResponsiveExtension : MarkupExtension, IResponsiveCallback

#if SUPPORTS_XAML_SERVICE_PROVIDER
internal WeakReference? TargetWeakRef { get; private set; }
private Type? _propertyType;
private DependencyProperty? _targetProperty;
#endif
internal ResolvedLayout<object?>? ResolvedValue { get; private set; }
Expand Down Expand Up @@ -90,10 +96,20 @@ public ResponsiveExtension()
var match = defs.FirstOrNull(y => y.MinWidth >= size.Width) ?? defs.LastOrNull();
var resolved = match?.Value;

#if DEBUG
LastUsedLayout = layout;
#endif
ResolvedValue = resolved;

return resolved?.Value;
var result = resolved?.Value;
#if SUPPORTS_XAML_SERVICE_PROVIDER
if (result != null && _propertyType != null && result.GetType() != _propertyType)
{
result = XamlCastSafe(result, _propertyType);
}
#endif

return result;
}

#if SUPPORTS_XAML_SERVICE_PROVIDER
Expand All @@ -102,11 +118,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)
target.FindDependencyPropertyUsingReflection($"{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
target.GetType().GetProperty(pvtp.Name, Public | Instance | FlattenHierarchy)?.PropertyType;
#else
pvtp.Type;
#endif
// 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
Expand All @@ -116,7 +137,7 @@ pvt.TargetProperty is ProvideValueTargetProperty pvtp &&
target.Loaded += OnTargetLoaded;

#if DEBUG
TrackedInstances.Add((TargetWeakRef, pvtp!.Name, new WeakReference(this)));
TrackedInstances.Add((TargetWeakRef, pvtp.Name, new WeakReference(this)));
#endif
}
else
Expand Down Expand Up @@ -150,6 +171,23 @@ public void OnSizeChanged(Size size, ResponsiveLayout layout)
#endif
}

private static object? XamlCastSafe(object value, Type type)
{
try
{
return XamlBindingHelper.ConvertValue(type, value);
}
catch (Exception)
{
if (_logger.IsEnabled(LogLevel.Error))
{
_logger.LogError($"Failed to convert value from '{value.GetType().Name}' to '{type.Name}'");
}

return value;
}
}

internal ResponsiveLayout? GetAppliedLayout() =>
Layout ??
(TargetWeakRef?.Target as FrameworkElement)?.ResolveLocalResource<ResponsiveLayout>(ResponsiveLayout.DefaultResourceKey);
Expand Down

0 comments on commit 11e8909

Please sign in to comment.