2008-12-03 8 views
2

Je développe le contrôle Web Gridview en tant que première tentative de création d'un contrôle personnalisé.Affichage des classes de ressources fortement typées disponibles dans la fenêtre de propriétés

Dans le cadre de l'extension, j'encapsule la localisation des en-têtes de colonne dans le contrôle. Entre autres, j'expose quelques propriétés pour activer cette fonction:

bool AutoLocalizeColumnHeaders - permet la fonction

chaîne HeaderResourceFile - identifie une classe de ressource fortement typé dont pour obtenir le texte d'en-tête

Je remplace le gestionnaire OnRowDataBound et obtenant le ResourceManager approprié utilisant Reflection pour remplir le texte d'en-tête. Tout cela fonctionne bien, mais je voudrais afficher une liste des classes de ressources Strongly Typed disponibles dans la fenêtre de propriétés pour que l'utilisateur puisse choisir, plutôt que d'avoir à taper le nom manuellement.

J'ai créé un TypeConverter pour afficher une liste déroulante dans laquelle afficher les classes disponibles, mais je ne peux pas déterminer comment afficher la liste des noms de classe disponibles.

J'ai essayé pendant un bon moment maintenant sans succès et je suis sur le point de perdre ma santé mentale. Je suppose qu'il doit y avoir un moyen d'y parvenir en utilisant Reflection?

Répondre

0

Idée intéressante. J'imagine que votre propriété est actuellement définie comme une chaîne? Je me demande si vous définissez votre propriété comme Enum, puis créez un Enum avec les classes de ressources fortement typées, sera-t-il assez intelligent pour les afficher dans la fenêtre de propriétés. il est assez intelligent pour le montrer dans le code derrière, je ne vois pas pourquoi il ne pourrait pas le charger dans la fenêtre des propriétés.

1

Je pense que j'ai trouvé la solution maintenant.

exécutant ce qui suit à l'intérieur d'un événement Page_Load m'a donné les noms de classe de ressources:

String[] resourceClassNames = (from type in assembly.GetTypes() 
    where type.IsClass && type.Namespace.Equals("Resources") 
    select type.Name).ToArray(); 

Je pensais que je serais capable de faire quelque chose de similaire de la fonction à l'intérieur des GetResourceFileNames (ITypeDescriptorContext contexte) du TypeConverter , en utilisant le paramètre de contexte pour obtenir l'assemblage correct. Malheureusement, je ne pouvais que sembler obtenir l'assembly du Custom Control ou l'assembly System.Web. Donc, j'ai créé un UITypeEditor qui a un IServiceProvider passé dans la routine EditValue. De cela, je suis en mesure de créer une instance de ITypeDiscoveryService que je puis utilisé pour obtenir tous les types de l'assemblage correct:

public override object EditValue(ITypeDescriptorContext context, 
           IServiceProvider provider, object value) 
{ 
    // Check if all the expected parameters are here 
    if (context == null || context.Instance == null || provider == null) 
    { 
     // returning with the received value 
     return base.EditValue(context, provider, value); 
    } 

    // Create the Discovery Service which will find all of the available classes 
    ITypeDiscoveryService discoveryService = (ITypeDiscoveryService)provider.GetService(typeof(ITypeDiscoveryService)); 
    // This service will handle the DropDown functionality in the Property Grid 
    _wfes = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService; 

    // Create the DropDown control for displaying in the Properties Grid 
    System.Windows.Forms.ListBox selectionControl = new System.Windows.Forms.ListBox(); 
    // Attach an eventhandler to close the list after an item has been selected 
    selectionControl.SelectedIndexChanged += new EventHandler(selectionControl_SelectedIndexChanged); 
    // Get all of the available types 
    ICollection colTypes = discoveryService.GetTypes(typeof(object), true); 
    // Enumerate the types and add the strongly typed 
    // resource class names to the selectionControl 
    foreach (Type t in colTypes) 
    { 
     if (t.IsClass && t.Namespace.Equals("Resources")) 
     { 
      selectionControl.Items.Add(t.Name); 
     } 
    } 
    if (selectionControl.Items.Count == 0) 
    { 
     selectionControl.Items.Add("No Resources found"); 
    } 
    // Display the UI editor combo 
    _wfes.DropDownControl(selectionControl); 

    // Return the new property value from the UI editor combo 
    if (selectionControl.SelectedItem != null) 
    { 
     return selectionControl.SelectedItem.ToString(); 
    } 
    else 
    { 
     return base.EditValue(context, provider, value); 
    } 
} 

void selectionControl_SelectedIndexChanged(object sender, EventArgs e) 
{ 
    _wfes.CloseDropDown(); 
} 

Cela semble bien fonctionner même si je pense qu'il ya un moyen plus élégant pour obtenir les types requis à l'aide de LinQ, mais je viens juste de commencer à regarder LinQ et je n'arrive pas à obtenir la syntaxe correcte lors de l'interrogation d'une collection plutôt que d'un tableau comme dans l'exemple précédent.

Si n'importe qui peut suggérer la syntaxe de LinQ qui ferait ceci ou en effet, une meilleure manière d'accomplir l'ensemble, alors ce serait le bienvenu.

0

Dans ma solution tition, je voulais trouver un moyen de faire ce qui suit LINQ:

// Get all of the available types 
    System.Collections.ICollection colTypes = discoveryService.GetTypes(typeof(object), true); 
    // Enumerate the types and add the strongly typed resource class names to the selectionControl 
    foreach (Type t in colTypes) 
    { 
     if (t.IsClass && t.Namespace.Equals("Resources")) 
     { 
      selectionControl.Items.Add(t.Name); 
     } 
    } 

Cela semble faire l'affaire:

// Get all of the available class names from the Resources namespace 
    var resourceClassNames = from Type t in discoveryService.GetTypes(typeof(object), true) 
         where t.IsClass && t.Namespace.Equals("Resources") 
         select t.Name; 

    selectionControl.Items.AddRange(resourceClassNames.ToArray()); 

Il semble certainement beaucoup plus propre et je suppose que c'est plus performant car il ne boucle pas sur tous les types disponibles, en vérifiant ceux qui répondent aux critères de mon code; bien que je suppose que LinQ ferait cela pour moi, quoique d'une manière plus efficace?