2008-09-22 4 views
23

J'ai un tableau int en tant que propriété d'un contrôle utilisateur Web. Je voudrais définir cette ligne de propriété, si possible, en utilisant la syntaxe suivante:Passer un tableau int comme paramètre dans le contrôle utilisateur Web

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

Cela échouera lors de l'exécution, car il sera attend un tableau int réel, mais une chaîne est d'être passé à la place. Je peux faire myintarray une chaîne et l'analyser dans le setter, mais je me demandais s'il y avait une solution plus élégante.

+1

Question intéressante ... – juan

Répondre

20

Mettre en oeuvre un convertisseur de type, voici un, avertissement: rapide & sale, pas pour la production, 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(); 
    } 
} 

et la balise la propriété de votre contrôle:

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

J'ai ajouté un exemple ci-dessous qui va compiler. Merci! – ern

+0

Ce n'est pas suffisant. Voir http://weblogs.asp.net/bleroy/405013 –

5

me semble que l'approche — et — plus extensible logique est de prendre une page des contrôles de liste asp::

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

Merci. Cela peut fonctionner, mais c'est beaucoup de code supplémentaire à l'avant. J'essaie de rester aussi minimaliste que possible. – ern

0

ce qu'il faut faire ce que le projet de loi parlait avec la liste que vous avez juste besoin de créer une propriété List sur votre utilisateur c ontrol. Ensuite, vous pouvez l'implémenter comme décrit dans le projet de loi.

0

Vous pouvez ajouter aux événements de page à l'intérieur quelque chose comme ASPX ceci:

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

Pour ajouter des éléments enfants qui font votre liste, vous devez avoir votre configuration de contrôle d'une certaine façon:

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

Les actions ci-dessus sont le nom de la propriété c les éléments enfants seront po. J'utilise un ArrayList, comme je n'ai rien testé d'autre avec:

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

lorsque votre contorl est initialisé, il aura les valeurs des éléments enfants. Ceux que vous pouvez faire une mini classe qui ne contient que des ints.

0

Vous pouvez implémenter une classe de convertisseur de type qui convertit entre les types de données int array et string. Décorez ensuite votre propriété int array avec TypeConverterAttribute, en spécifiant la classe que vous avez implémentée. Visual Studio utilisera ensuite votre convertisseur de type pour les conversions de type sur votre propriété.

6

@mathieu, merci beaucoup pour votre code.Je l'ai modifié quelque peu afin de compiler:

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

J'ai corrigé la réponse originale, vous pouvez supprimer celui-ci si vous voulez – juan

+1

(je l'ai corrigé avec votre code bien sûr) – juan

2

Vous pouvez aussi faire quelque chose comme ceci:

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

qui se traduira par:

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

Cela ne fonctionne pas pour moi – SashaArz

2

Grand extrait @mathieu. J'avais besoin de l'utiliser pour convertir des longs, mais plutôt que de faire un LongArrayConverter, j'ai écrit une version qui utilise 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(); 
    } 
} 

Cette version devrait fonctionner avec n'importe quel type qui est convertible à partir d'une chaîne.

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