在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解析器到达此部分时,我必须定义某种形式的字符串到键盘的转换,似乎无法找到我需要做的回答。
问题的答案在Petzold的漂亮的《 [[Xamarin.Forms》一书中很好地解释了(您可以免费下载here!]。)>在 第7章...您可以在XAML中包括自定义类,并且这些类可以具有自定义类型的属性,或者这些属性可以是标准类型,但允许附加值。您所需要做的就是使用C#TypeConverter属性标记这些类型或属性,并提供派生自TypeConverter的类。
还有一些好奇的细节
(从上述书中简单引用)在那章中,Petzold通过给出一个带有Label的示例来说明这一点:
<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的HorizontalTextAlignment属性的类型为TextAlignment,它是一个枚举。对于任何属于枚举类型的属性,XAML解析器都使用Enum.Parse方法将字符串从值转换为值。
The 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属性。
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); }