【问题标题】:Xamarin custom MarkupExtension not working with Type propertyXamarin 自定义 MarkupExtension 不适用于 Type 属性
【发布时间】:2018-08-24 14:19:19
【问题描述】:

我正在尝试使用 Type 作为属性在 Xamarin 表单中创建自定义 MarkupExtension。不幸的是,我无法传递Type 的属性,在我的情况下,该属性始终为null。这是我的 MarkupExtension 的最小示例,将类型的全名返回为字符串:

[ContentProperty(nameof(TheType))]
public class TypeMarkupExtension : IMarkupExtension
{
    public Type TheType { get; set; }

    public object ProvideValue(IServiceProvider serviceProvider)
    {

        return TheType?.FullName ?? "Failure";
    }
}

但是我尝试过,使用 MarkupExtension 是不可能的,因为TheType 始终是null,而我的返回值是"Failure"。这是我尝试使用扩展的方式,例如:

<Label Text="{local:TypeMarkup x:Int16}"/>
<Label Text="{local:TypeMarkup {x:Type x:Int16}}"/>

如果我使用简单的string 作为属性类型,则代码可以完美运行。对我来说,通过Type 似乎是不可能的。这是正确的还是我的代码有问题?

【问题讨论】:

    标签: c# xaml xamarin xamarin.forms


    【解决方案1】:

    选项 1:指定属性名称

    您需要在此处使用嵌套标记扩展(您已经这样做了);但您还需要指定属性的名称。否则,我的测试显示,它被视为字符串值并分配给默认内容属性 - 因此,类型不匹配。

    因此,如下明确指定属性名称应该可以解决问题:

    <Label Text="{local:TypeMarkup TheType={x:Type x:Int16}}" ../>
    

    选项 2:使用 Xaml 类型解析器

    您可以使用XamlTypeResolver(参考:TypeExtension in Xamarin.Forms

    [ContentProperty(nameof(TheType))]
    public class TypeMarkupExtension : IMarkupExtension
    {
        public string TheType { get; set; }
    
        public object ProvideValue(IServiceProvider serviceProvider)
        {
            if (string.IsNullOrEmpty(TheType))
                throw new InvalidOperationException("TheType isn't set.");
            
            if (serviceProvider == null)
                throw new ArgumentNullException(nameof(serviceProvider));
    
            var typeResolver = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver;
            if (typeResolver == null)
                throw new ArgumentException("No IXamlTypeResolver in IServiceProvider");
    
            var resolvedType = typeResolver.Resolve(TheType, serviceProvider);
            return resolvedType?.FullName ?? "Failure";
        }
    }
    

    【讨论】:

    • 完美答案,这完全解决了我的问题,非常感谢。对您的第二个解决方案的一个小补充:在我看来,使用 TypeExtension te = new TypeExtension() { TypeName = TheType }; 之类的现有实现并使用 Te.ProvideValue(ServiceProvider); 获取类型是一个非常聪明的解决方案。
    猜你喜欢
    • 2021-08-18
    • 1970-01-01
    • 1970-01-01
    • 2016-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-15
    • 1970-01-01
    相关资源
    最近更新 更多