我正在研究初始化XAML中声明的泛型类型的成员.这是针对WPF 4和将来的Silverlight中的(reduced) generics support. (我已经在VS2010 Beta 2中使用x:TypeArguments和XamlReader.Load尝试了以下方案,但为简单起见,将使用TestClassInt32:TestClass< int> {},因为它的行为与直接使用泛型类型相同,但更容易今天使用已编译的xaml进行测试.)
这是我正在使用的测试类型.
public class TestClass<T> {
[TypeConverter( typeof(StringListToItemsConverter) )]
public IEnumerable<T> Items { get; set; }
public TestProperty<T> Property { get; set; }
}
[TypeConverter( typeof(TestPropertyConverter) )]
public struct TestProperty<T> {
public TestProperty( T value ) : this() { Value = value; }
public T Value { get; }
}
这是示例方案.
<StackPanel>
<StackPanel.DataContext>
<test:TestClassInt32 Items="1,2,3" Property="6" />
</StackPanel.DataContext>
<TextBox Text="{Binding Property.Value}" />
<ItemsControl ItemsSource="{Binding Items}" />
</StackPanel>
在本例中,当我将typeof(int)硬编码到转换器中时,一切正常,但是该方法显然不适用于TestClass< double>.或TestClass< DateTime>.问题在于TypeConverter.ConvertFrom方法无法访问目标类型,而只能访问源类型. (在.NET 1.0中创建TypeConverter时,这不是问题,因为无法对目标类型进行参数化,但是现在是一个不幸的限制.)
>使类型转换器通用;例如[TypeConverter(typeof(TestPropertyConverter< T>)))]
> .NET不支持属性中的类型参数
>让TypeConverter返回实现IConvertible.ToType或has a TypeConvert
that can ConvertTo
the destination type的中间类型
> XAML解析器仅执行一步转换:如果无法将返回的对象分配给目标,则抛出异常
>定义一个自定义类型描述符,该描述符将根据实际类型返回适当的转换器
> WPF忽略自定义类型描述符,并且TypeDescriptor在Silverlight中甚至不存在
这是我为“解决”此问题而提出的替代方案:
>要求将目标类型嵌入到字符串中;例如“ sys:Double 1,2,3”
>在Silverlight中,必须对一组固定的受支持类型进行硬编码(在WPF中,可以使用IXamlTypeResolver接口来获取“ sys:Double”对应的实际类型)
>编写一个带有类型参数的自定义标记扩展;例如“ {列表类型= {x:类型sys:Double},值= 1,2,3}”
> Silverlight不支持自定义标记扩展(它也不支持x:Type标记扩展,但是您可以使用选项1中的硬编码方法)
>创建一个带有类型参数的包装器类型,并将所有通用成员重新定义为对象,并将所有成员访问转发给基础的强类型对象
>可能,但是会带来非常差的用户体验(必须进行强制转换以获取基础的通用对象,必须在Silverlight上仍使用硬编码的列表作为类型参数,必须缓存成员分配,直到分配了类型参数,依此类推,等等. ;通常会失去使用泛型进行强类型键入的大部分好处)
今天或在WPF 4中,很高兴听到其他任何解决此问题的想法.
解决方法:
在.NET 4中,有一个IServiceProvider可用,您可以通过它获得IDestinationTypeProvider
,然后您应该可以执行所需的操作.
在.NET 3或4中,IProvideValueTarget
服务可以为您提供targetobject和targetProperty.从targetProperty(属性信息,附加的MethodInfo或DependencyProperty)中,可以获取类型.
例如,要从TypeConverter的ConvertFrom中获取IDestinationTypeProvider服务提供者:
public override object ConvertFrom(
ITypeDescriptorContext context,
CultureInfo culture,
object value )
{
var typeProvider =
(IDestinationTypeProvider)context.GetService( typeof( IDestinationTypeProvider ) );
Type targettype = typeProvider.GetDestinationType();
// ... do stuff
return base.ConvertFrom( context, culture, value );
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。