目标是在没有构造函数注入和静态资源的情况下实例化local:MyViewModel
。
<Label.BindingContext>local:MyViewModel</Label.BindingContext>
我尝试使用XML属性语法
<Label ... BindingContext="{local:MyViewModel}"/>
但是Visual Studio Community用
警告我类型
local:MyViewModel
用作标记扩展,但不是从MarkupExtension派生的。
问题:
- 忽略此警告是否安全?
- 有什么技巧可以抑制警告吗?
这是WPF的标记扩展实现。检查它是否也能在Xamarin中工作。
using System;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Markup;
namespace CommonCore
{
[MarkupExtensionReturnType(typeof(Type))]
public class CreateInstanceExtension : MarkupExtension
{
[ConstructorArgument("instanceType")]
[DefaultValue(null)]
public Type InstanceType { get; set; }
[ConstructorArgument("instanceValue")]
[DefaultValue(null)]
public string InstanceValue { get; set; }
public CreateInstanceExtension(Type instanceType, string instanceValue)
: this(instanceValue)
{
InstanceType = instanceType;
}
public CreateInstanceExtension(string instanceValue)
: this()
{
InstanceValue = instanceValue;
}
public CreateInstanceExtension()
{ }
private static TypeExtension typeExtension;
public override object ProvideValue(IServiceProvider serviceProvider)
{
Type type = InstanceType;
string value = InstanceValue;
if (type is null)
{
value = value?.Trim(" trn".ToCharArray());
if (!string.IsNullOrEmpty(value))
{
string typeName = null;
if (value[0] == '(')
{
int end = value.IndexOf(')');
if (end > 0)
{
typeName = value.Substring(1, end - 1);
value = value.Substring(end + 1).Trim(" trn".ToCharArray());
}
}
else
{
typeName = value;
value = null;
}
if (!string.IsNullOrEmpty(typeName))
{
(typeExtension ??= new TypeExtension()).TypeName = typeName;
type = (Type)typeExtension.ProvideValue(serviceProvider);
}
}
}
if (type is null)
{
throw new NullReferenceException("The type must be specified.");
}
if (string.IsNullOrEmpty(value))
{
return Activator.CreateInstance(type);
}
else
{
if (TypeDescriptor.GetConverter(type) is not TypeConverter converter)
{
throw new NotImplementedException("There is no TypeConverter for the specified type.");
}
var target = ((IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget)))?.TargetObject as FrameworkElement;
if (target?.Language.GetEquivalentCulture() is CultureInfo culture)
return converter.ConvertFromString(null, culture, value);
return converter.ConvertFromInvariantString(value);
}
}
}
}
在WPF中的用法:
<Label ... DataContext="{commcore:CreateInstance (local:MyViewModel)}"/>
<Label ... DataContext="{commcore:CreateInstance local:MyViewModel}"/>
<Label ... DataContext="{commcore:CreateInstance (sys:Double)123.456}"/>