【问题标题】:Xamarin.Forms - The mechanism about text contain in x:String in XAMLXamarin.Forms - 关于文本的机制包含在 XAML 中的 x:String 中
【发布时间】:2021-07-20 11:35:02
【问题描述】:

我很好奇为什么 x:String 或其他可以在 xaml 打开和关闭选项卡中包含文本的原始类型。

如下代码所示:

    <x:String>String content here!</x:String>

和Xamarin.Forms“Label”一样,它在类的顶部装饰[ContentProperty("Text")],我们可以这样写代码

   <Label>Hello</Label>

但是,在 x:String 标记中,我找不到任何装饰。

谁能帮我解决我的问题?

【问题讨论】:

  • &lt;x:String&gt; 的定义由在 XAML 顶部定义的任何命名空间 x 确定。阅读这些声明行,以及如何为每个声明的命名空间找到相应的规范。 (我意识到x 是“标准”之一,但我认为在这里解释基本原理会更有帮助;然后你可以探索任何你想要的声明。)抱歉,我不记得链接解释了什么“标准”命名空间。
  • 所以你的意思是,命名空间 x 中的类型将自动处理所有这些事情,就像 UI 控件装饰“ContentProperty”一样,但以另一种方式。
  • 和ContentProperty有点不同,ContentProperty是用来设置一个已有的属性作为内容,但是这里的只是markup extension 的一种,我们可以设置里面的值。

标签: c# xaml xamarin.forms


【解决方案1】:

让我们暂时忘掉x:String,专注于Thickness。显然你可以这样创建Thickness 的实例:

<Thickness>1,1,1,1</Thickness>

现在,让我们将其与创建Label 进行比较:

<Label>Hello</Label>

虽然两条线看起来很相似,但它们做的事情却不同。使用Label,它创建Label 的实例(使用默认的无参数构造函数)并将Hello 分配给它的Text 属性(如Label 类的[ContentProperty("Text")] 属性所指示的那样)。但Thickness 并非如此。您不能只创建Thickness 的实例并将值1,1,1,1 分配给它的一个属性。有两个问题:

  1. Thickness 没有字符串属性来接受逗号分隔值并初始化其 Bottom、Right、Top、Left 属性。
  2. 更糟糕的是,Thickness 不是一个类。它是一个结构,因此它没有无参数的构造函数。那么 Xamarin 如何决定需要将哪些参数传递给它的构造函数呢?

现在您可以清楚地看到 ContentProperty 属性不是让我们能够做到的:&lt;Thickness&gt;1,1,1,1&lt;/Thickness&gt;。此处 Xamarin.Forms 采用字符串值 1,1,1,1 并将其转换为 Thickness 的实例。这是通过 Xamarin.Forms 中的 TypeConverters 完成的。您可以通过检查 [TypeConverter(typeof(ThicknessTypeConverter))] 上的 Thickness 结构来验证这一点。

我认为这个想法与 Xamarin.Forms 中的内置原始类型相同。例如,当您编写 &lt;x:Boolean&gt;True&lt;/x:Boolean&gt; 时,Xamarin.Forms 会使用字符串 True 并在其内部 TypeConverters 的帮助下将其转换为 System.Boolean。

奖励:如果您想使用自己的自定义结构实现相同的行为(我认为类不可能),您可以执行以下操作:

  1. 创建一个自定义 TypeConverter 以指示 Xamarin.Forms 如何将字符串值转换为结构的实例:

    public class MyPointConverter : Xamarin.Forms.TypeConverter
    {
        public override object ConvertFromInvariantString(string value)
        {
            var parts = value.Split(new[] { ',' }, StringSplitOptions.None);
    
            if (parts.Length != 2
                || !int.TryParse(parts[0], out var x)
                || !int.TryParse(parts[1], out var y))
            {
                return base.ConvertFromInvariantString(value);
            }
    
            var myPoint = new MyPoint(x, y);
    
            return myPoint;
        }
    }
    
  2. 使用TypeConverterAttribute 装饰您的结构,以显示自定义TypeConverter 可用于此类型:

    [Xamarin.Forms.TypeConverter(typeof(MyPointConverter))]
    public struct MyPoint
    {
        public int X { get; set; }
        public int Y { get; set; }
    
        public MyPoint(int x, int y)
        {
            this.X = x;
            this.Y = y;
        }
    }
    
  3. 在 Xaml 中创建结构的实例:

    <ResourceDictionary>
        <local:MyPoint x:Key="MyPoint">1,5</local:MyPoint>
    </ResourceDictionary>
    

【讨论】:

  • 哇,这对我来说真的很清楚。谢谢你。我很感激。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多