我有一个int数组作为Web用户控件的属性。如果可能的话,我想使用以下语法设置该属性:
<uc1:mycontrol runat="server" myintarray="1,2,3" />
这将在运行时失败,因为它将期待一个实际的int数组,但是传递了一个字符串。我可以使myintarray
成为一个字符串并在setter中解析它,但我想知道是否有更优雅的解决方案。
答案 0 :(得分:20)
实现类型转换器,这里是一个,警告:快速和脏,不用于生产用途等:
public class IntArrayConverter : System.ComponentModel.TypeConverter
{
public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
string val = value as string;
string[] vals = val.Split(',');
System.Collections.Generic.List<int> ints = new System.Collections.Generic.List<int>();
foreach (string s in vals)
ints.Add(Convert.ToInt32(s));
return ints.ToArray();
}
}
并标记控件的属性:
private int[] ints;
[TypeConverter(typeof(IntsConverter))]
public int[] Ints
{
get { return this.ints; }
set { this.ints = value; }
}
答案 1 :(得分:6)
@mathieu,非常感谢您的代码。为了编译,我稍微修改了一下:
public class IntArrayConverter : System.ComponentModel.TypeConverter
{
public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
string val = value as string;
string[] vals = val.Split(',');
System.Collections.Generic.List<int> ints = new System.Collections.Generic.List<int>();
foreach (string s in vals)
ints.Add(Convert.ToInt32(s));
return ints.ToArray();
}
}
答案 2 :(得分:5)
在我看来,逻辑和更具扩展性的方法是从asp:
列表控件中获取页面:
<uc1:mycontrol runat="server">
<uc1:myintparam>1</uc1:myintparam>
<uc1:myintparam>2</uc1:myintparam>
<uc1:myintparam>3</uc1:myintparam>
</uc1:mycontrol>
答案 3 :(得分:3)
伟大的片段@mathieu。我需要使用它来转换longs,但是我写了一个使用Generics的版本,而不是制作LongArrayConverter。
public class ArrayConverter<T> : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
string val = value as string;
if (string.IsNullOrEmpty(val))
return new T[0];
string[] vals = val.Split(',');
List<T> items = new List<T>();
Type type = typeof(T);
foreach (string s in vals)
{
T item = (T)Convert.ChangeType(s, type);
items.Add(item);
}
return items.ToArray();
}
}
此版本适用于任何可从字符串转换的类型。
[TypeConverter(typeof(ArrayConverter<int>))]
public int[] Ints { get; set; }
[TypeConverter(typeof(ArrayConverter<long>))]
public long[] Longs { get; set; }
[TypeConverter(typeof(ArrayConverter<DateTime))]
public DateTime[] DateTimes { get; set; }
答案 4 :(得分:2)
您是否尝试过查看类型转换器?此页面看起来值得一看:http://www.codeguru.com/columns/VB/article.php/c6529/
此外,Spring.Net似乎有一个StringArrayConverter(http://www.springframework.net/doc-latest/reference/html/objects-misc.html - 第6.4节),如果您可以通过使用TypeConverter属性修饰属性将其提供给ASP.net,则可能有效..
答案 5 :(得分:2)
您也可以这样做:
namespace InternalArray
{
/// <summary>
/// Item for setting value specifically
/// </summary>
public class ArrayItem
{
public int Value { get; set; }
}
public class CustomUserControl : UserControl
{
private List<int> Ints {get {return this.ItemsToList();}
/// <summary>
/// set our values explicitly
/// </summary>
[PersistenceMode(PersistenceMode.InnerProperty), TemplateContainer(typeof(List<ArrayItem>))]
public List<ArrayItem> Values { get; set; }
/// <summary>
/// Converts our ArrayItem into a List<int>
/// </summary>
/// <returns></returns>
private List<int> ItemsToList()
{
return (from q in this.Values
select q.Value).ToList<int>();
}
}
}
将导致:
<xx:CustomUserControl runat="server">
<Values>
<xx:ArrayItem Value="1" />
</Values>
</xx:CustomUserControl>
答案 6 :(得分:1)
要添加构成列表的子元素,您需要以某种方式设置控件:
[ParseChildren(true, "Actions")]
[PersistChildren(false)]
[ToolboxData("<{0}:PageActionManager runat=\"server\" ></PageActionManager>")]
[NonVisualControl]
public class PageActionManager : Control
{
上面的动作是子元素所在的cproperty的名称。我使用了一个ArrayList,因为我没有用它测试任何其他内容。:
private ArrayList _actions = new ArrayList();
public ArrayList Actions
{
get
{
return _actions;
}
}
初始化contorl时,它将具有子元素的值。那些你可以制作一个只持有整数的迷你课程。
答案 7 :(得分:0)
请使用您在用户控件上创建List属性所需的列表来执行Bill所讨论的内容。然后你可以像Bill描述的那样实现它。
答案 8 :(得分:0)
您可以在aspx中添加这样的页面事件:
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
YourUserControlID.myintarray = new Int32[] { 1, 2, 3 };
}
</script>
答案 9 :(得分:0)
您可以实现一个在int数组和字符串数据类型之间进行转换的类型转换器类。 然后使用TypeConverterAttribute修饰int数组属性,指定您实现的类。然后,Visual Studio将使用您的类型转换器对您的属性进行类型转换。
答案 10 :(得分:0)
如果在父控件之一上使用DataBinding,则可以使用DataBinding表达式:
<uc1:mycontrol runat="server" myintarray="<%# new [] {1, 2, 3} %>" />
使用自定义表达式生成器,您可以执行类似的操作。表达式生成器:
[ExpressionPrefix("Code")]
public class CodeExpressionBuilder : ExpressionBuilder
{
public override CodeExpression GetCodeExpression(System.Web.UI.BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context)
{
return new CodeSnippetExpression(entry.Expression.Trim());
}
}
用法:
<uc1:mycontrol runat="server" myintarray="<%$ Code: new [] {1, 2, 3} %>" />