Pregunta

Tengo una matriz int como propiedad de un control de usuario web.Me gustaría establecer esa propiedad en línea si es posible usando la siguiente sintaxis:

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

Esto fallará en tiempo de ejecución porque esperará una matriz int real, pero en su lugar se pasará una cadena.yo puedo hacer myintarray una cadena y analizarla en el configurador, pero me preguntaba si había una solución más elegante.

¿Fue útil?

Solución

Implemente un convertidor de tipos, aquí hay uno, advertencia:rápido y sucio, no para uso en producción, etc.:

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

y etiqueta la propiedad de tu control:

private int[] ints;
[TypeConverter(typeof(IntsConverter))]
public int[] Ints
{
    get { return this.ints; }
    set { this.ints = value; }
}

Otros consejos

@mathieu, muchas gracias por tu código.Lo modifiqué un poco para compilar:

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

Me parece que el enfoque lógico (y más extensible) es tomar una página del asp: controles de lista:

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

Gran fragmento @mathieu.Necesitaba usar esto para convertir largos, pero en lugar de crear un LongArrayConverter, escribí una versión que usa genéricos.

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

Esta versión debería funcionar con cualquier tipo que sea convertible a partir de una cadena.

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

¿Has intentado buscar convertidores de tipos?Parece que vale la pena echarle un vistazo a esta página: http://www.codeguru.com/columns/VB/article.php/c6529/

Además, Spring.Net parece tener un StringArrayConverter (http://www.springframework.net/doc-latest/reference/html/objects-misc.html - sección 6.4) que, si puede enviarlo a ASP.net decorando la propiedad con un atributo TypeConverter, podría funcionar.

También puedes hacer algo como esto:

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

lo que resultará en:

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

Para agregar elementos secundarios que formen su lista, necesita configurar su control de cierta manera:

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

Las acciones anteriores son el nombre de la propiedad en la que estarán los elementos secundarios.Utilizo un ArrayList, ya que no he probado nada más con él:

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

cuando se inicialice su control, tendrá los valores de los elementos secundarios.Esos pueden crear una mini clase que solo contenga enteros.

Haga lo que Bill estaba hablando con la lista, solo necesita crear una propiedad Lista en su control de usuario.Luego puedes implementarlo como lo describió Bill.

Podrías agregar a los eventos de la página dentro del aspx algo como esto:

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

Puede implementar una clase de convertidor de tipos que convierta entre tipos de datos de cadena y de matriz int.Luego decore su propiedad de matriz int con TypeConverterAttribute, especificando la clase que implementó.Luego, Visual Studio usará su convertidor de tipos para las conversiones de tipos en su propiedad.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top