Asp.net 在web用户控件中将int数组作为参数传递

Asp.net 在web用户控件中将int数组作为参数传递,asp.net,web-user-controls,Asp.net,Web User Controls,我有一个int数组作为Web用户控件的属性。如果可能,我希望使用以下语法将该属性设置为内联: <uc1:mycontrol runat="server" myintarray="1,2,3" /> 这将在运行时失败,因为它需要一个实际的int数组,但传递的是一个字符串。我可以将myintarray制作成一个字符串并在setter中解析它,但我想知道是否有更优雅的解决方案。您尝试过寻找类型转换器吗?此页面看起来值得一看: 另外,Spring.Net似乎有一个StringArray

我有一个int数组作为Web用户控件的属性。如果可能,我希望使用以下语法将该属性设置为内联:

<uc1:mycontrol runat="server" myintarray="1,2,3" />


这将在运行时失败,因为它需要一个实际的int数组,但传递的是一个字符串。我可以将
myintarray
制作成一个字符串并在setter中解析它,但我想知道是否有更优雅的解决方案。

您尝试过寻找类型转换器吗?此页面看起来值得一看:


另外,Spring.Net似乎有一个StringArrayConverter(-第6.4节),如果您可以通过使用TypeConverter属性装饰属性将其提供给ASP.Net,那么它可能会工作。

在我看来,逻辑性和可扩展性更强的方法是从
ASP:
列表控件中获取一个页面:

<uc1:mycontrol runat="server">
    <uc1:myintparam>1</uc1:myintparam>
    <uc1:myintparam>2</uc1:myintparam>
    <uc1:myintparam>3</uc1:myintparam>
</uc1:mycontrol>

1.
2.
3.

按照Bill所说的那样处理列表,只需在用户控件上创建一个list属性即可。然后,您可以按照Bill所述实现它。

您可以向aspx内的页面事件添加如下内容:

<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
    YourUserControlID.myintarray = new Int32[] { 1, 2, 3 };
}
</script>
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>();
        }
    }
}

受保护的无效页面加载(对象发送方、事件参数e)
{
YourUserControlID.myintarray=newint32[]{1,2,3};
}

要添加列表中的子元素,您需要以某种方式设置控件:

[ParseChildren(true, "Actions")]
[PersistChildren(false)]
[ToolboxData("<{0}:PageActionManager runat=\"server\" ></PageActionManager>")]
[NonVisualControl]
public class PageActionManager : Control
{

初始化控件时,它将具有子元素的值。您可以创建一个只包含int的迷你类。

实现一个类型转换器,下面是一个,警告:quick&dirty,不用于生产,等等:

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();
    }
}

可以实现在int数组和字符串数据类型之间转换的类型转换器类。
然后用TypeConverterAttribute修饰int数组属性,指定实现的类。Visual Studio随后将使用您的类型转换器对您的属性进行类型转换。

@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();
    }
}
公共类IntArrayConverter:System.ComponentModel.TypeConverter
{
公共覆盖布尔CanConvertFrom(System.ComponentModel.ITypeDescriptorContext上下文,类型sourceType)
{
返回sourceType==typeof(字符串);
}
公共重写对象ConvertFrom(System.ComponentModel.ITypeDescriptorContext上下文,System.Globalization.CultureInfo区域性,对象值)
{
字符串val=作为字符串的值;
字符串[]vals=val.Split(',');
System.Collections.Generic.List ints=新的System.Collections.Generic.List();
foreach(VAL中的字符串s)
ints.Add(转换为32(s));
返回ints.ToArray();
}
}

您也可以这样做:

<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
    YourUserControlID.myintarray = new Int32[] { 1, 2, 3 };
}
</script>
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>();
        }
    }
}
命名空间内部数组
{
/// 
///用于专门设置值的项目
/// 
公共类数组项
{
公共int值{get;set;}
}
公共类CustomUserControl:UserControl
{
私有列表int{get{返回this.ItemsToList();}
/// 
///明确地设定我们的价值观
/// 
[PersistenceMode(PersistenceMode.InnerProperty),TemplateContainer(typeof(List))]
公共列表值{get;set;}
/// 
///将我们的ArrayItem转换为列表
/// 
/// 
私有列表项stolist()
{
返回值(从该.Values中的q开始)
选择q.Value).ToList();
}
}
}
这将导致:

<xx:CustomUserControl  runat="server">
  <Values>
            <xx:ArrayItem Value="1" />
  </Values>
</xx:CustomUserControl>

伟大的代码片段@mathieu。我需要使用它来转换long,但我编写了一个使用泛型的版本,而不是制作longarayconverter

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();
    }
}
公共类ArrayConverter:TypeConverter
{
公共覆盖布尔CanConvertFrom(ITypeScriptorContext上下文,类型sourceType)
{
返回sourceType==typeof(字符串);
}
公共重写对象ConvertFrom(ITypeDescriptorContext上下文、CultureInfo区域性、对象值)
{
字符串val=作为字符串的值;
if(string.IsNullOrEmpty(val))
返回新的T[0];
字符串[]vals=val.Split(',');
列表项=新列表();
类型=类型(T);
foreach(VAL中的字符串s)
{
T item=(T)Convert.ChangeType(s,type);
项目。添加(项目);
}
返回项目。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; }
[TypeConverter(typeof(ArrayConverter))]
公共int[]int{get;set;}
[TypeConverter(typeof(ArrayConverter))]
公共长[]长{get;set;}

[TypeConverter(typeof(ArrayConverter如果在父控件之一上使用数据绑定,则可以使用数据绑定表达式:

<uc1:mycontrol runat="server" myintarray="<%# new [] {1, 2, 3} %>" />
用法:

<uc1:mycontrol runat="server" myintarray="<%$ Code: new [] {1, 2, 3} %>" />


谢谢。这可能有用,但前面有很多额外的代码。我正在尽可能地保持最低限度。我在下面添加了一个可以编译的示例。谢谢!我修复了原始答案,如果你愿意,可以删除这个
<uc1:mycontrol runat="server" myintarray="<%$ Code: new [] {1, 2, 3} %>" />