标签FontSize OnPlatform TypeArguments加倍导致Xamarin.Forms中出现错误

时间:2019-02-14 03:35:45

标签: xamarin xamarin.forms

我做了一些研究,但找不到针对自己问题的答案。我有一个XF应用,并使用以下代码设置Label的样式:

<Style x:Key="Heading2Text" TargetType="Label">
   <Setter Property="FontSize">
      <Setter.Value>
         <OnPlatform x:TypeArguments="x:Double">
            <On Platform="iOS" Value="{DynamicResource Heading2TextFontSizeiOS}"/>
            <On Platform="Android" Value="{DynamicResource Heading2TextFontSizeAndroid}"/>
         </OnPlatform>
      </Setter.Value>
   </Setter>
</Style>

在我的资源中:

Current.Resources["Heading2TextFontSizeiOS"] = 10.75 * vScale;
Current.Resources["Heading2TextFontSizeAndroid"] = 20.5 * vScale;

这给我一个错误:Specified cast is not valid

但是,如果我像下面的代码那样指定值,那么它将起作用。

<Style x:Key="Heading2Text" TargetType="Label">
   <Setter Property="FontSize">
      <Setter.Value>
         <OnPlatform x:TypeArguments="x:Double">
            <On Platform="iOS" Value="14"/>
            <On Platform="Android" Value="20"/>
         </OnPlatform>
      </Setter.Value>
   </Setter>
</Style>

有人知道我在做什么错吗?

编辑:

我意识到了问题所在。 Current.Resources["Heading2TextFontSizeiOS"]是一个对象,因此是错误。有人对如何解决这个问题有什么建议吗?

vScaleApp.xaml.cs中这样声明:

public static double vScale;

在资源类中:

vScale = height > 700 ? 1.4 : height / 568;

这是我得到的例外:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidCastException: Specified cast is not valid.
  at Xamarin.Forms.OnPlatform`1[T].op_Implicit (Xamarin.Forms.OnPlatform`1[T] onPlatform) [0x00036] in D:\a\1\s\Xamarin.Forms.Core\OnPlatform.cs:75 
  at (wrapper managed-to-native) System.Reflection.MonoMethod.InternalInvoke(System.Reflection.MonoMethod,object,object[],System.Exception&)
  at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x0003b] in <d4a23bbd2f544c30a48c44dd622ce09f>:0 
   --- End of inner exception stack trace ---
  at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00054] in <d4a23bbd2f544c30a48c44dd622ce09f>:0 
  at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] in <d4a23bbd2f544c30a48c44dd622ce09f>:0 
  at Xamarin.Forms.BindableProperty.TryConvert (System.Object& value) [0x000cf] in D:\a\1\s\Xamarin.Forms.Core\BindableProperty.cs:341 
  at Xamarin.Forms.BindableObject.SetValueCore (Xamarin.Forms.BindableProperty property, System.Object value, Xamarin.Forms.Internals.SetValueFlags attributes, Xamarin.Forms.BindableObject+SetValuePrivateFlags privateAttributes) [0x00041] in D:\a\1\s\Xamarin.Forms.Core\BindableObject.cs:386 
  at Xamarin.Forms.BindableObject.SetValue (Xamarin.Forms.BindableProperty property, System.Object value, System.Boolean fromStyle, System.Boolean checkAccess) [0x0003d] in D:\a\1\s\Xamarin.Forms.Core\BindableObject.cs:572 
  at Xamarin.Forms.BindableObject.SetValue (Xamarin.Forms.BindableProperty property, System.Object value, System.Boolean fromStyle) [0x00000] in D:\a\1\s\Xamarin.Forms.Core\BindableObject.cs:356 
  at Xamarin.Forms.Setter.Apply (Xamarin.Forms.BindableObject target, System.Boolean fromStyle) [0x000ba] in D:\a\1\s\Xamarin.Forms.Core\Setter.cs:75 
  at Xamarin.Forms.Style.ApplyCore (Xamarin.Forms.BindableObject bindable, Xamarin.Forms.Style basedOn) [0x0001e] in D:\a\1\s\Xamarin.Forms.Core\Style.cs:132 
  at Xamarin.Forms.Style.Xamarin.Forms.IStyle.Apply (Xamarin.Forms.BindableObject bindable) [0x0002b] in D:\a\1\s\Xamarin.Forms.Core\Style.cs:95 
  at Xamarin.Forms.MergedStyle.SetStyle (Xamarin.Forms.IStyle implicitStyle, System.Collections.Generic.IList`1[T] classStyles, Xamarin.Forms.IStyle style) [0x00156] in D:\a\1\s\Xamarin.Forms.Core\MergedStyle.cs:180 
  at Xamarin.Forms.MergedStyle.set_Style (Xamarin.Forms.IStyle value) [0x00000] in D:\a\1\s\Xamarin.Forms.Core\MergedStyle.cs:37 
  at Xamarin.Forms.NavigableElement+<>c.<.cctor>b__20_0 (Xamarin.Forms.BindableObject bindable, System.Object oldvalue, System.Object newvalue) [0x00000] in D:\a\1\s\Xamarin.Forms.Core\Shell\NavigableElement.cs:16 
  at Xamarin.Forms.BindableObject.SetValueActual (Xamarin.Forms.BindableProperty property, Xamarin.Forms.BindableObject+BindablePropertyContext context, System.Object value, System.Boolean currentlyApplying, Xamarin.Forms.Internals.SetValueFlags attributes, System.Boolean silent) [0x00120] in D:\a\1\s\Xamarin.Forms.Core\BindableObject.cs:624 
  at Xamarin.Forms.BindableObject.SetValueCore (Xamarin.Forms.BindableProperty property, System.Object value, Xamarin.Forms.Internals.SetValueFlags attributes, Xamarin.Forms.BindableObject+SetValuePrivateFlags privateAttributes) [0x0015b] in D:\a\1\s\Xamarin.Forms.Core\BindableObject.cs:422 
  at Xamarin.Forms.BindableObject.SetValue (Xamarin.Forms.BindableProperty property, System.Object value, System.Boolean fromStyle, System.Boolean checkAccess) [0x0003d] in D:\a\1\s\Xamarin.Forms.Core\BindableObject.cs:572 
  at Xamarin.Forms.BindableObject.SetValue (Xamarin.Forms.BindableProperty property, System.Object value) [0x00000] in D:\a\1\s\Xamarin.Forms.Core\BindableObject.cs:122 
  at Xamarin.Forms.VisualElement.set_Style (Xamarin.Forms.Style value) [0x00000] in D:\a\1\s\Xamarin.Forms.Core\VisualElement.cs:394 

1 个答案:

答案 0 :(得分:0)

有两件事要看。

第一:

这是将基于XAML的DynamicResourceOnPlatform结合使用的当前限制。

这应该可以,但不能:

        <Style x:Key="Heading2Text" TargetType="Button">
            <Style.Setters>
                <Setter Property="FontSize">
                    <OnPlatform x:TypeArguments="x:Double">
                        <On Platform="Android">
                            <DynamicResource Key="Heading2TextFontSizeAndroid"  />
                        </On>
                    </OnPlatform>
                    </Setter>
            </Style.Setters>
        </Style>

可以通过代码进行操作:

someLabelInstance.SetDynamicResource(Label.FontSizeProperty, "Heading2TextFontSizeAndroid");
Resources["Heading2TextFontSizeAndroid"] = 10 * 4.0;

注意:我已经看到这个问题飘浮了很多年,因此,如果有一种方法可以直接在XAML中使用带有OnPlatform的DynamicResource,而不是将其转换为StaticResource的方法,那么我很乐意看到

如果将其转换为使用StaticResource,它将起作用,但是,如果您确实需要以动态方式更改这些属性,那当然是不可能的。

第二:

您是否真的需要将其作为动态绑定的属性?

似乎这可能是您正在执行的设备特定计算,因此只能执行一次。另外,静态资源更快,占用的内存更少,因为所有动态资源基本上都是绑定的属性。

如果可以在实例化ContentPage之前计算vScale = height > 700 ? 1.4 : height / 568;,并且在该页面实例的生存期内不进行更改,则可以使用StaticResource并首先更新其值。

示例:

应用级资源:

<sys:Double x:Key="Heading2TextFontSizeAndroid">20</sys:Double>

页面级资源样式:

<Style x:Key="Heading2Text" TargetType="Button">
    <Style.Setters>
        <Setter Property="FontSize">
            <OnPlatform x:TypeArguments="x:Double">
                <On Platform="Android">
                    <StaticResource Key="Heading2TextFontSizeAndroid"  />
                </On>
            </OnPlatform>
            </Setter>
    </Style.Setters>
</Style>

代码:

// Before you instance the page that `Heading2TextFontSizeAndroid` will be use in
vScale = height > 700 ? 1.4 : height / 568;
Resources["Heading2TextFontSizeAndroid"] = vScale;

// Now you can instance the page and `vScale` is applied
var page = new SomeContentPage();