【问题标题】:How to set custom property value with Type other than String in XAML [Xamarin.Forms]如何在 XAML [Xamarin.Forms] 中使用 String 以外的类型设置自定义属性值
【发布时间】:2020-04-27 13:06:36
【问题描述】:

在 XAML 中的 Xamarin.Forms 中,您可以编写如下内容:

<Entry Keyboard="Plain" />

我发现了 Entry 类,Keyboard 属性的类型是 Xamarin.Forms.Keyboard。但是,如果我创建自己的自定义 ContentView 并在里面写这样的内容:

    public static readonly BindableProperty KeyboardProperty = BindableProperty.Create
    (
        propertyName: "Keyboard",
        returnType: typeof(Keyboard),
        declaringType: typeof(MyCustomContentView),
        defaultValue: Keyboard.Default,
        defaultBindingMode: BindingMode.TwoWay,
        propertyChanged: (bindable, oldValue, newValue) =>
        {
            // some unrelated stuff here
        }
    );
    public Keyboard Keyboard
    {
        get => (Keyboard)GetValue(KeyboardProperty);
        set => SetValue(KeyboardProperty, value);
    }

我不能为我自己的内容视图使用相同的 XAML 格式。显然它是一个简单的字符串,它期望Xamarin.Forms.Keyboard 类的实例。到目前为止,我发现它与KeyboardProperty 或绑定无关,而是Keyboard 属性本身(如果我是正确的)。我相信它与ValueConverters 有关,当 XAML 解析器到达这部分时,我必须定义某种形式的字符串到键盘的转换,只是似乎无法找到我需要做的答案。

【问题讨论】:

    标签: c# xaml xamarin.forms converters


    【解决方案1】:

    Petzold 在他关于 Xamarin.Forms 的精美书中很好地解释了您的问题的答案(您可以免费下载 here!)。

    第 7 章属性和属性部分的末尾,您可以阅读

    ...您可以在 XAML 中包含自定义类,这些类可以具有自定义类型的属性,或者这些属性可以是标准类型但允许附加值。您只需使用 C# TypeConverter 属性标记这些类型或属性,并提供派生自 TypeConverter 的类。

    还有一些细节供好奇的人参考

    (仅引用自上述书籍)

    在那一章中,Petzold 通过给出一个带有标签的示例来说明这一点:

    <Label Text="Hello from XAML!"        
           IsVisible="True"
           Opacity="0.75" 
           HorizontalTextAlignment="Center" 
           VerticalOptions="CenterAndExpand" 
           TextColor="Blue" 
           BackgroundColor="#FF8080" 
           FontSize="Large" 
           FontAttributes="Bold,Italic" /> 
    

    然后继续解释 XAML 如何设置这些属性。

    XAML 的简洁主要源于属性值的简洁性——例如,使用“Large”一词而不是调用 Device.GetNamedSize 方法。这些缩写未内置到 XAML 解析器中。 XAML 解析器由专门为此目的定义的各种转换器类来辅助。

    当 XAML 解析器遇到 Label 元素时,它可以使用反射来确定 Xamarin.Forms 是否有一个名为 Label 的类,如果有,它可以实例化该类。现在它已准备好初始化该对象。 Text 属性是字符串类型,属性值只是分配给该属性。

    Label 的 IsVisible 和 Opacity 属性分别是 bool 和 double 类型,它们和您想象的一样简单。 XAML 分析器使用 Boolean.Parse 和 Double.Parse 方法来转换属性值。 Boolean.Parse 方法不区分大小写,但通常布尔值在 XAML 中大写为“True”和“False”。 Double.Parse 方法传递了一个 CultureInfo.InvariantCulture 参数,因此转换不依赖于程序员或用户的本地文化。

    Label 的Horizo​​ntalTextAlignment 属性是TextAlignment 类型,它是一个枚举。对于任何枚举类型的属性,XAML 解析器使用 Enum.Parse 方法将字符串转换为值。

    VerticalOptions 属性属于 LayoutOptions 类型,一种结构。当 XAML 解析器使用反射引用 LayoutOptions 结构时,它发现该结构定义了 C# 属性:

    [TypeConverter (typeof(LayoutOptionsConverter))] 
    public struct LayoutOptions 
    { 
        … 
    }
    

    TypeConverter 属性由名为 TypeConverterAttribute 的类支持。 LayoutOptions 上的这个特定 TypeConverter 属性引用了一个名为 LayoutOptionsConverter 的类,该类派生自一个名为 TypeConverter 的公共抽象类,该类定义了名为 CanConvertFrom 和 ConvertFrom 的方法。当 XAML 分析器遇到此 TypeConverter 属性时,它会实例化 LayoutOptionsConverter。 XAML 中的 VerticalOptions 属性分配了字符串“Center”,因此 XAML 解析器将该“Center”字符串传递给 LayoutOptionsConverter 的 ConvertFrom 方法,并弹出一个 LayoutOptions 值。这被分配给 Label 对象的 VerticalOptions 属性。

    【讨论】:

      【解决方案2】:

      完全回答问题。创建这个类:

      using System;
      using Xamarin.Forms;
      
      public class KeyboardTypeConverter : TypeConverter
      {
          public override bool CanConvertFrom(Type sourceType)
          {
              return sourceType == typeof(string);
          }
      
          public override object ConvertFromInvariantString(string value)
          {
              switch (value)
              {
                  case "Chat": return Keyboard.Chat;
                  case "Email": return Keyboard.Email;
                  case "Numeric": return Keyboard.Numeric;
                  case "Plain": return Keyboard.Plain;
                  case "Telephone": case "Phone": return Keyboard.Telephone;
                  case "Text": return Keyboard.Text;
                  case "Url": return Keyboard.Url;
                  default: return Keyboard.Default;
              }
          }
      }
      

      然后将TypeConverter 属性添加到Keyboard 属性:

      using System.Reflection;
      
      using Xamarin.Forms;
      using Xamarin.Forms.Xaml;
      
      [TypeConverter(typeof(KeyboardTypeConverter))]
      public Keyboard Keyboard
      {
          get => (Keyboard)GetValue(KeyboardProperty);
          set => SetValue(KeyboardProperty, value);
      }
      

      【讨论】:

        猜你喜欢
        • 2023-04-02
        • 1970-01-01
        • 2010-12-10
        • 2020-11-11
        • 2014-08-10
        • 2012-09-09
        • 2021-01-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多