24

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

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

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

4

11 回答 11

20

实现一个类型转换器,这是一个,警告: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();
    }
}

并标记您的控件的属性:

private int[] ints;
[TypeConverter(typeof(IntsConverter))]
public int[] Ints
{
    get { return this.ints; }
    set { this.ints = value; }
}
于 2008-09-22T19:52:25.260 回答
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();
    }
}
于 2008-09-22T20:45:57.987 回答
5

在我看来,合乎逻辑且更具可扩展性的方法是从asp:列表控件中获取一个页面:

<uc1:mycontrol runat="server">
    <uc1:myintparam>1</uc1:myintparam>
    <uc1:myintparam>2</uc1:myintparam>
    <uc1:myintparam>3</uc1:myintparam>
</uc1:mycontrol>
于 2008-09-22T19:26:56.833 回答
4

很棒的片段@mathieu。我需要使用它来转换 long,但我没有制作 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; }
于 2012-02-22T16:57:02.137 回答
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 节),如果你可以将它提供给 ASP.net用 TypeConverter 属性装饰属性,可能会起作用..

于 2008-09-22T19:23:59.460 回答
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>
于 2009-11-23T11:45:34.880 回答
1

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

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

上面的 Actions 是子元素所在的 cproperty 的名称。我使用 ArrayList,因为我没有用它测试任何其他内容。:

        private ArrayList _actions = new ArrayList();
    public ArrayList Actions
    {
        get
        {
            return _actions;
        }
    }

当您的 contorl 初始化时,它将具有子元素的值。那些你可以制作一个只包含整数的迷你类。

于 2008-09-22T19:43:22.677 回答
0

做比尔所说的,你只需要在你的用户控件上创建一个 List 属性。然后您可以按照 Bill 的描述来实现它。

于 2008-09-22T19:30:59.287 回答
0

您可以在 aspx 中添加页面事件,如下所示:

<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
    YourUserControlID.myintarray = new Int32[] { 1, 2, 3 };
}
</script>
于 2008-09-22T19:38:36.353 回答
0

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

于 2008-09-22T20:07:03.413 回答
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} %>" />
于 2020-08-24T14:26:23.350 回答