如何在 XAML [Xamarin.Forms] 中使用 String 以外的类型设置自定义属性值
Posted
技术标签:
【中文标题】如何在 XAML [Xamarin.Forms] 中使用 String 以外的类型设置自定义属性值【英文标题】:How to set custom property value with Type other than String in XAML [Xamarin.Forms] 【发布时间】: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 解析器到达这部分时,我必须定义某种形式的字符串到键盘的转换,只是似乎无法找到我需要做的答案。
【问题讨论】:
【参考方案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 的HorizontalTextAlignment 属性是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);
【讨论】:
以上是关于如何在 XAML [Xamarin.Forms] 中使用 String 以外的类型设置自定义属性值的主要内容,如果未能解决你的问题,请参考以下文章
如何根据 Xamarin.Forms xaml 中的本地化语言显示选取器项目
XAML中的Xamarin.Forms ListView AutoHeight
如何使用 xamarin.forms-shell 在 XAML 中动态绑定类型为 <ShellContent> 的 Tab.Items 列表