Передача массива int в качестве параметра в веб-элемент управления - PullRequest
23 голосов
/ 22 сентября 2008

У меня есть массив int как свойство веб-элемента управления пользователя. Я хотел бы установить это свойство встроенным, если это возможно, используя следующий синтаксис:

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

Это не удастся во время выполнения, поскольку он будет ожидать фактического массива int, но вместо этого будет передана строка. Я могу сделать myintarray строку и разобрать ее в установщике, но мне было интересно, есть ли более элегантное решение.

Ответы [ 10 ]

20 голосов
/ 22 сентября 2008

Реализовать преобразователь типов, вот один, предупреждение: быстро и грязно, не для производственного использования и т. Д .:

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; }
}
6 голосов
/ 23 сентября 2008

@ 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();
    }
}
5 голосов
/ 22 сентября 2008

Мне кажется, что логический и более расширяемый подход - это взять страницу из списка элементов управления asp::

<uc1:mycontrol runat="server">
    <uc1:myintparam>1</uc1:myintparam>
    <uc1:myintparam>2</uc1:myintparam>
    <uc1:myintparam>3</uc1:myintparam>
</uc1:mycontrol>
3 голосов
/ 22 февраля 2012

Отличный фрагмент @mathieu. Мне нужно было использовать это для преобразования длинных, но вместо создания LongArrayConverter я написал версию, которая использует Generics.

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; }
2 голосов
/ 23 ноября 2009

Вы также можете сделать что-то вроде этого:

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>
2 голосов
/ 22 сентября 2008

Вы пробовали смотреть на преобразователи типов? Эта страница выглядит достойной внимания: 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, может сработать. *

1 голос
/ 22 сентября 2008

Чтобы добавить дочерние элементы, которые составляют ваш список, вам нужно настроить свой элемент управления следующим образом:

[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;
        }
    }

когда ваш контроллер инициализируется, он будет иметь значения дочерних элементов. Те, которые вы можете сделать мини-класс, который просто держит целые.

0 голосов
/ 23 сентября 2008

Вы можете реализовать класс преобразователя типов, который преобразует между массивом int и строковыми типами данных. Затем украсьте свойство массива int с помощью TypeConverterAttribute, указав класс, который вы реализовали. Затем Visual Studio будет использовать конвертер типов для преобразования типов в вашем имуществе.

0 голосов
/ 22 сентября 2008

Вы можете добавить на страницу событий внутри aspx что-то вроде этого:

<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
    YourUserControlID.myintarray = new Int32[] { 1, 2, 3 };
}
</script>
0 голосов
/ 22 сентября 2008

Делайте то, о чем говорил Билл, со списком, вам просто нужно создать свойство List в вашем пользовательском элементе управления. Затем вы можете реализовать это, как описано Биллом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...