2011-04-22 6 views
1

Je veux avoir un « forme » ou quelque chose d'autre (peu importe) qui peut ajouter la chaîne à une listeCommunication composant au moment du design

il serait fait avec un premier composant « StringManager » sorcière contient D'autre part, je veux avoir un autre composant "ComponentReader" qui utilise IExtenderProvider et ajouter sur toutes les commandes (sur le formulaire de composant) une propriété nommée "TheString" qui me laisse choisir dans l'une des chaînes de Liste

Donc, pour être ar: je veux partager le List<String> avec le minimum de code sur chaque formes, (le plus avec l'éditeur de propriétés)

Je ne sais pas comment puis-je dire le "ComponentReader" où est le composant principal qu'il se réfère, (J'ai ajouté une propriété ReferedStringManager dans mon "ComponentReader").

est-il des propriétés ou instruction (ou moyen) à inspectent le projet et ses références pour obtenir toutes valeur matchable comme liste dans « ComponentReader » propriétés pour la propriété ReferedStringManager du ComponentReader;

Si ce ne est pas possible, je pense à la liste statique ou autre chose, fichier XML peut-être, (mais je ne sais pas comment gérer que lors de la conception)

Bien sûr, tout cela est au moment du design, pas au moment de l'exécution (ce serait tellement plus simple !!)

+0

Peut-être que vous devriez sauvegarder et expliquer le problème de votre « solution » proposée vise à résoudre. Il se peut qu'il existe une autre façon de résoudre le problème original. – Tergiver

+0

Je veux juste apprendre si je peux le faire ... et comment le faire, peut-être plus d'une solution ... – guillaume

Répondre

1

Ceci est une réponse tardive, mais si vous êtes toujours intéressé, voici comment le faire.

Il existe de nombreuses exigences pour vos classes StringManager et ComponentReader.

1) les deux classes doivent dériver de System.ComponentModel.Component.

2) Le StringManager doit remplacer la propriété Site de la classe Component. C'est ce qui le rend "conscient de VS Designer", et lui permet d'être sélectionnable dans les propriétés de votre ComponentReader plus tard.

3) Le StringManager doit exposer la liste en tant que propriété publique. Pour plus de commodité, dans mon exemple de code, j'ai défini l'éditeur EditorAttribute pour faciliter l'édition de collection de chaînes dans la grille de propriétés VS.

4) Le ComponentReader doit implémenter une interface personnalisée avec une seule propriété de type StringManager. Ceci est requis par l'exigence # 6.

5) Le ComponentReader doit avoir une propriété publique de type StringManager

6) Le ComponentReader doit avoir une propriété publique de type chaîne pour le SelectedString. Le hic est que nous devons définir le TypeConverterAttribute à encore une autre classe que nous devons implémenter (voir # 7)

7) Nous devons implémenter une classe dérivée StringConverter. Cela sera utilisé pour nous permettre de sélectionner une chaîne du StringManager sélectionné.Dans cette classe, nous devons être en mesure de récupérer une référence à ComponentReader via l'interface créée au # 4.

Maintenant, pour le code:

StringManager.cs

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.ComponentModel; 
using System.Windows.Forms; 
using System.ComponentModel.Design; 

namespace VSDesignHost 
{ 
class StringManager : Component 
{ 
    private ContainerControl _containerControl = null; 

    public StringManager() 
    { 
     TheList = new List<string>(); 
    } 

    public StringManager(IContainer container) : this() 
    { 
     container.Add(this); 

     InitializeComponent(); 
    } 

    private void InitializeComponent() 
    { 
     //Whatever 
    } 

    public ContainerControl ContainerControl 
    { 
     get { return _containerControl; } 
     set { _containerControl = value; } 
    } 

    public override ISite Site 
    { 
     set 
     { 
      base.Site = value; 
      if (value != null) 
      { 
       IDesignerHost host = value.GetService(typeof(IDesignerHost)) as IDesignerHost; 
       if (host != null) 
       { 
        IComponent rootComponent = host.RootComponent; 
        if (rootComponent is ContainerControl) 
        { 
         this.ContainerControl = (ContainerControl)rootComponent; 
        } 
       } 
      } 
     } 
    } 

    [Editor("System.Windows.Forms.Design.StringCollectionEditor, System.Design", "System.Drawing.Design.UITypeEditor, System.Drawing")] 
    public List<string> TheList { get; set; } 

} 
} 

ComponentReader.cs

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.ComponentModel; 

namespace VSDesignHost 
{ 
    class ComponentReader : Component, IStringManagerEnabled 
    { 
     private StringManager sm; 

     public ComponentReader() 
     { 
      sm = null; 
     } 

     [Browsable(true), Category("MyCategory")] 
     public StringManager StringManager 
     { 
      get { return sm; } 
      set 
      { 
       sm = value; 
      } 
     } 

     [Browsable(true), Category("MyCategory"), TypeConverter(typeof(StringManagerStringConverter))] 
     public string SelectedString { get; set; } 

    } 
} 

IStringManagerEnabled.cs:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace VSDesignHost 
{ 
    interface IStringManagerEnabled 
    { 
     StringManager StringManager 
     { 
      get; 
      set; 
     } 
    } 
} 

StringManagerStringConverter.cs:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.ComponentModel; 

namespace VSDesignHost 
{ 
    class StringManagerStringConverter : StringConverter 
    { 
     #region Make It A ComboBox 
     public override bool GetStandardValuesSupported(ITypeDescriptorContext context) 
     { 
      return true; 
     } 
     public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) 
     { 
      return false; 
     } 
     #endregion 


     #region Display Tags In List 
     public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) 
     { 
      if ((context == null) || (context.Container == null)) 
      { 
       return null; 
      } 

      Object[] Tags = this.GetTagsFromServer(context); 
      if (Tags != null) 
      { 
       return new StandardValuesCollection(Tags); 
      } 
      return null; 
     } 

     private object[] GetTagsFromServer(ITypeDescriptorContext context) 
     { 
      List<string> availableTags = new List<string>(); 

      if (context.Instance == null) 
      { 
       availableTags.Add("ITypeDescriptorContext.Instance is null"); 
       return availableTags.ToArray(); 
      } 


      IStringManagerEnabled inst = context.Instance as IStringManagerEnabled; 
      if (inst == null) 
      { 
       availableTags.Add(context.Instance.ToString()); 
       return availableTags.ToArray(); 
      } 

      if (inst.StringManager == null) 
      { 
       availableTags.Add("No StringManager selected"); 
       return availableTags.ToArray(); 
      } 

      availableTags = inst.StringManager.TheList; 
      availableTags.Sort(Comparer<string>.Default); 
      return availableTags.ToArray(); 
     } 

     #endregion 



     public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 
     { 
      if (sourceType == typeof(string)) 
       return true; 
      return base.CanConvertFrom(context, sourceType); 
     } 

     public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) 
     { 
      if (value is string) 
       return value.ToString(); 
      return base.ConvertFrom(context, culture, value); 
     } 

    } 
} 

Créez un projet Windows Forms, ajoutez-y ces fichiers et générez le projet. Maintenant, sur votre formulaire, vous pouvez ajouter une instance de chaque StringManager et ComponentReader en faisant glisser depuis la boîte à outils.

Sélectionnez le StringManager et, dans les propriétés, ajoutez une chaîne à TheList en utilisant l'éditeur de collection de chaînes.

Sélectionnez ComponentReader, et dans les fenêtres de propriétés, vous devriez pouvoir sélectionner votre instance StringManager dans la liste déroulante.

Vous devriez maintenant pouvoir sélectionner l'une des chaînes dans la liste déroulante de SelectedString.

J'espère que vous apprécierez

Luc

Questions connexes