如何在这样的xaml中使用泛型?
dataObsevable.pipe(withLatestFrom(scrollEvents)).subscribe(([list, e]) => {
this.data = list;
if (e.position) {
viewPort.scrollToPosition(e.position);
} else {
viewPort.scrollToPosition([0, 0]);
}
});
答案 0 :(得分:1)
您有两种方法:
第一个解决方案(非常快):只需编写类似
public class ListOfStrings : List<String>
{
}
然后
<dxprg:PropertyGridControl SelectedObject="{Binding Argument}">
<dxprg:PropertyDefinition Type="{x:Type local:ListOfStrings}" />
</dxprg:PropertyGridControl>
第二种解决方案可能稍微复杂一些,但并非没有可能。您可以找到一个很好的Markup Extension for Generic Classes on CodeProject。
我只是根据您的方便复制代码:
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Windows.Markup;
using System.Xaml;
using System.Xaml.Schema;
namespace XamlGenericTypeExtension
{
[ContentProperty("TypeArguments")]
[MarkupExtensionReturnType(typeof(Type))]
public class GenericTypeExtension : MarkupExtension
{
private readonly List<Type> _typeArguments = new List<Type>();
private string _typeName;
private Type _type;
public GenericTypeExtension(string typeName)
{
if (string.IsNullOrEmpty(typeName)) throw new ArgumentNullException("typeName");
_typeName = typeName;
}
public GenericTypeExtension(string typeName, Type typeArgument)
: this(typeName)
{
if (typeArgument != null)
{
_typeArguments.Add(typeArgument);
}
}
public GenericTypeExtension(string typeName, Type typeArgument1, Type typeArgument2)
: this(typeName, typeArgument1)
{
if (typeArgument2 != null)
{
_typeArguments.Add(typeArgument2);
}
}
public GenericTypeExtension(string typeName, Type typeArgument1, Type typeArgument2, Type typeArgument3)
: this(typeName, typeArgument1, typeArgument2)
{
if (typeArgument3 != null)
{
_typeArguments.Add(typeArgument3);
}
}
public GenericTypeExtension(string typeName, Type typeArgument1, Type typeArgument2, Type typeArgument3, Type typeArgument4)
: this(typeName, typeArgument1, typeArgument2, typeArgument3)
{
if (typeArgument4 != null)
{
_typeArguments.Add(typeArgument4);
}
}
public GenericTypeExtension()
{
}
public string BaseTypeName
{
get
{
return _typeName;
}
set
{
if (string.IsNullOrEmpty(value)) throw new ArgumentNullException("value");
_typeName = value;
_type = null;
}
}
[TypeConverter(typeof(TypeArgumentsConverter))]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public IList TypeArguments
{
get
{
return _typeArguments;
}
set
{
_typeArguments.Clear();
if (null != value && 0 != value.Count)
{
_typeArguments.AddRange(value.OfType<Type>());
}
}
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (serviceProvider == null) throw new ArgumentNullException("serviceProvider");
if (_type == null)
{
if (string.IsNullOrEmpty(_typeName))
{
throw new InvalidOperationException("No base type name was specified.");
}
if (_typeArguments.Count == 0)
{
_type = ResolveNonGenericType(serviceProvider, _typeName);
}
else
{
_type = ResolveGenericType(serviceProvider, _typeName, _typeArguments.ToArray());
}
}
return _type;
}
private static Type ResolveNonGenericType(IServiceProvider serviceProvider, string typeName)
{
var resolver = GetRequiredService<IXamlTypeResolver>(serviceProvider);
Type type = resolver.Resolve(typeName);
if (type == null)
{
throw new InvalidOperationException(string.Format("Unable to resolve type '{0}'.", typeName));
}
return type;
}
private static Type ResolveGenericType(IServiceProvider serviceProvider, string typeName, Type[] typeArguments)
{
string namespaceName;
string[] splitTypeName = typeName.Split(':');
if (2 == splitTypeName.Length)
{
namespaceName = splitTypeName[0];
typeName = splitTypeName[1];
}
else
{
namespaceName = string.Empty;
}
var resolver = GetRequiredService<IXamlNamespaceResolver>(serviceProvider);
var schema = GetRequiredService<IXamlSchemaContextProvider>(serviceProvider);
var xamlNs = resolver.GetNamespace(namespaceName);
string genericTypeName = string.Format(CultureInfo.InvariantCulture, "{0}`{1:D}", typeName, typeArguments.Length);
var xamlTypeName = new XamlTypeName(xamlNs, genericTypeName);
var xamlType = schema.SchemaContext.GetXamlType(xamlTypeName);
if (xamlType == null)
{
throw new InvalidOperationException(string.Format("Unable to resolve type '{0}'.", xamlTypeName));
}
Type genericType = xamlType.UnderlyingType;
if (genericType == null)
{
throw new InvalidOperationException(string.Format("Unable to resolve type '{0}'.", xamlTypeName));
}
return genericType.MakeGenericType(typeArguments);
}
private static T GetRequiredService<T>(IServiceProvider serviceProvider) where T : class
{
var result = serviceProvider.GetService(typeof(T)) as T;
if (null != result) return result;
throw new InvalidOperationException(string.Format(
"Markup extension '{0}' requires '{1}' be implemented in the IServiceProvider for ProvideValue.",
typeof(GenericTypeExtension).Name,
typeof(T).Name));
}
}
}
和
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Windows.Markup;
namespace XamlGenericTypeExtension
{
public class TypeArgumentsConverter : TypeConverter
{
public override Boolean CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(Type)) return true;
if (context == null) return false;
var resolver = context.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver;
return resolver != null;
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value == null || value is IList<Type>) return value;
Type valueType = value as Type;
if (valueType != null)
{
return new List<Type> { valueType };
}
string valueString = value as string;
if (valueString != null && context != null)
{
var resolver = context.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver;
if (resolver != null)
{
var list = valueString.Split(',').Select(s => resolver.Resolve(s.Trim())).ToList();
if (list.All(t => t != null)) return list;
}
}
throw GetConvertFromException(value);
}
}
}
有关CodeProject的文章提供了有关如何使用它的信息。 希望它能对您有所帮助。