--- /dev/null
+using System;
+using System.Collections.Generic;
+using NUnit.Framework;
+using Xamarin.Forms;
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Gh7156 : ContentPage
+ {
+ public Gh7156() => InitializeComponent();
+ public Gh7156(bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [SetUp] public void Setup() => Device.PlatformServices = new MockPlatformServices();
+ [TearDown] public void TearDown() => Device.PlatformServices = null;
+
+ [Test]
+ public void OnPlatformDefaultToBPDefaultValue([Values(true, false)]bool useCompiledXaml)
+ {
+ ((MockPlatformServices)Device.PlatformServices).RuntimePlatform = Device.Android;
+ var layout = new Gh7156(useCompiledXaml);
+ Assert.That(layout.l0.Text, Is.EqualTo(Label.TextProperty.DefaultValue));
+ Assert.That(layout.l0.WidthRequest, Is.EqualTo(VisualElement.WidthRequestProperty.DefaultValue));
+ Assert.That(layout.l1.Text, Is.EqualTo("bar"));
+ Assert.That(layout.l1.WidthRequest, Is.EqualTo(20d));
+ }
+ }
+ }
+}
using System;
using System.Globalization;
using System.Reflection;
-using System.Xml;
namespace Xamarin.Forms.Xaml
{
[ContentProperty(nameof(Default))]
public class OnPlatformExtension : IMarkupExtension
{
- public object Default { get; set; }
- public object Android { get; set; }
- public object GTK { get; set; }
- public object iOS { get; set; }
- public object macOS { get; set; }
- public object Tizen { get; set; }
- public object UWP { get; set; }
- public object WPF { get; set; }
+ static object s_notset = new object();
+
+ public object Default { get; set; } = s_notset;
+ public object Android { get; set; } = s_notset;
+ public object GTK { get; set; } = s_notset;
+ public object iOS { get; set; } = s_notset;
+ public object macOS { get; set; } = s_notset;
+ public object Tizen { get; set; } = s_notset;
+ public object UWP { get; set; } = s_notset;
+ public object WPF { get; set; } = s_notset;
public IValueConverter Converter { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
- if ( Android == null
- && GTK == null
- && iOS == null
- && macOS == null
- && Tizen == null
- && UWP == null
- && WPF == null
- && Default == null) {
- throw new XamlParseException("OnPlatformExtension requires a non-null value to be specified for at least one platform or Default.", serviceProvider);
+ if ( Android == s_notset
+ && GTK == s_notset
+ && iOS == s_notset
+ && macOS == s_notset
+ && Tizen == s_notset
+ && UWP == s_notset
+ && WPF == s_notset
+ && Default == s_notset) {
+ throw new XamlParseException("OnPlatformExtension requires a value to be specified for at least one platform or Default.", serviceProvider);
}
var valueProvider = serviceProvider?.GetService<IProvideValueTarget>() ?? throw new ArgumentException();
PropertyInfo pi = null;
Type propertyType = null;
- if (valueProvider.TargetObject is Setter setter) {
+ if (valueProvider.TargetObject is Setter setter)
bp = setter.Property;
- }
else {
bp = valueProvider.TargetProperty as BindableProperty;
pi = valueProvider.TargetProperty as PropertyInfo;
}
propertyType = bp?.ReturnType
- ?? pi?.PropertyType
- ?? throw new InvalidOperationException("Cannot determine property to provide the value for.");
+ ?? pi?.PropertyType
+ ?? throw new InvalidOperationException("Cannot determine property to provide the value for.");
- var value = GetValue();
- var info = propertyType.GetTypeInfo();
- if (value == null && info.IsValueType)
- return Activator.CreateInstance(propertyType);
+ if (!TryGetValueForPlatform(out var value)) {
+ if (bp != null)
+ return bp.GetDefaultValue(valueProvider.TargetObject as BindableObject);
+ if (propertyType.GetTypeInfo().IsValueType)
+ return Activator.CreateInstance(propertyType);
+ return null;
+ }
if (Converter != null)
return Converter.Convert(value, propertyType, ConverterParameter, CultureInfo.CurrentUICulture);
return ret;
}
- object GetValue()
+ bool TryGetValueForPlatform(out object value)
{
- switch (Device.RuntimePlatform) {
- case Device.Android:
- return Android ?? Default;
- case Device.GTK:
- return GTK ?? Default;
- case Device.iOS:
- return iOS ?? Default;
- case Device.macOS:
- return macOS ?? Default;
- case Device.Tizen:
- return Tizen ?? Default;
- case Device.UWP:
- return UWP ?? Default;
- case Device.WPF:
- return WPF ?? Default;
- default:
- return Default;
+ if (Device.RuntimePlatform == Device.Android && Android != s_notset) {
+ value = Android;
+ return true;
+ }
+ if (Device.RuntimePlatform == Device.GTK && GTK != s_notset) {
+ value = GTK;
+ return true;
+ }
+ if (Device.RuntimePlatform == Device.iOS && iOS != s_notset) {
+ value = iOS;
+ return true;
+ }
+ if (Device.RuntimePlatform == Device.macOS && macOS != s_notset) {
+ value = macOS;
+ return true;
+ }
+ if (Device.RuntimePlatform == Device.Tizen && Tizen != s_notset) {
+ value = Tizen;
+ return true;
+ }
+ if (Device.RuntimePlatform == Device.UWP && UWP != s_notset) {
+ value = UWP;
+ return true;
+ }
+ if (Device.RuntimePlatform == Device.WPF && WPF != s_notset) {
+ value = WPF;
+ return true;
}
+ value = Default;
+ return value != s_notset;
}
}
-}
+}
\ No newline at end of file