2010-08-02 7 views
49

Je rencontre un problème qui consiste à convertir des chaînes d'entrée telles que "RED" au type de couleur réel Color.Red en C#. Y at-il un bon moyen de le faire?Convertir la chaîne en couleur en C#

Je pourrais penser à utiliser une instruction switch et une instruction case pour chaque type de couleur, mais je ne pense pas que ce soit assez intelligent.

Répondre

81
Color red = Color.FromName("Red"); 

Le MSDN ne dit pas d'une façon ou d'une autre, donc il y a une bonne chance que c'est le cas -sensible. (UPDATE: Apparemment, il ne l'est pas.)

Pour autant que je sache, ColorTranslator.FromHtml est également.

Si Color.FromName ne peut pas trouver un match, il retourne new Color(0,0,0);

Si ColorTranslator.FromHtml ne peut pas trouver un match, il jette une exception.

MISE À JOUR:

Puisque vous utilisez Microsoft.Xna.Framework.Graphics.Color, cela devient un peu délicat:

using XColor = Microsoft.Xna.Framework.Graphics.Color; 
using CColor = System.Drawing.Color; 

CColor clrColor = CColor.FromName("Red"); 
XColor xColor = new XColor(clrColor.R, clrColor.G, clrColor.B, clrColor.A); 
+0

Hey James, merci pour votre commentaire. Depuis que je développe cela dans le XNA GameStudio, après avoir entré votre code, le programme se plaint: Erreur 1 'Microsoft.Xna.Framework.Graphics.Color' ne contient pas de définition de ' FromName 'et aucune méthode d'extension' FromName 'acceptant un premier argument de type' Microsoft.Xna.Framework.Graphics.Color 'peut être trouvé (manque-t-il une directive using ou une référence d'assembly?) C: \ Users \ Guoguo \ Desktop \ MapWorld2 \ MapWorld \ GameObject.cs 194 27 MapWorld Considérez-vous l'erreur? – Kevin

+3

+1 pour mentionner le comportement différent lorsqu'aucune correspondance n'est trouvée. – Davy8

+0

Microsoft.Xna.Framework n'est pas le bon espace de noms. Use System.Drawing – StingyJack

16
System.Drawing.Color myColor = System.Drawing.ColorTranslator.FromHtml("Red"); 

(Utilisez ma méthode si vous voulez accepter les couleurs hexagonales de style HTML.)

-2

Je l'ai utilisé quelque chose comme ça avant:

 public static T CreateFromString<T>(string stringToCreateFrom) { 

     T output = Activator.CreateInstance<T>(); 

     if (!output.GetType().IsEnum) 
      throw new IllegalTypeException(); 

     try { 
      output = (T) Enum.Parse(typeof (T), stringToCreateFrom, true); 
     } 
     catch (Exception ex) { 
      string error = "Cannot parse '" + stringToCreateFrom + "' to enum '" + typeof (T).FullName + "'"; 
      _logger.Error(error, ex); 
      throw new IllegalArgumentException(error, ex); 
     } 

     return output; 
    } 
+0

Ce n'est pas une énumération. –

+0

@Jon j'ai été mélangé avec ConsoleColor. La même logique pourrait encore s'appliquer si ... pas vrai? Au lieu de Enum.Parse(), il peut faire une comparaison insensible à la casse sur les noms de propriétés et renvoyer le résultat. (en supprimant évidemment le contrôle IsEnum). – Skyler

+0

Je pense que trouver la propriété par réflexion à chaque fois serait relativement douloureux. Mieux, IMO, de construire un dictionnaire une fois (selon ma réponse). –

14

(Il aurait vraiment été bien si vous aviez mentionné quel type Color vous étiez intéressé à commencer par ...)

Une façon simple de le faire est de construire tout un dictionnaire par réflexion:

public static class Colors 
{ 
    private static readonly Dictionary<string, Color> dictionary = 
     typeof(Color).GetProperties(BindingFlags.Public | 
            BindingFlags.Static) 
        .Where(prop => prop.PropertyType == typeof(Color)) 
        .ToDictionary(prop => prop.Name, 
            prop => (Color) prop.GetValue(null, null))); 

    public static Color FromName(string name) 
    { 
     // Adjust behaviour for lookup failure etc 
     return dictionary[name]; 
    } 
} 

Ce sera relativement lent pour la première recherche (alors qu'il utilise la réflexion pour trouver toutes les propriétés), mais devrait être très rapide après ça.

Si vous voulez qu'il soit insensible à la casse, vous pouvez passer quelque chose comme StringComparer.OrdinalIgnoreCase comme argument supplémentaire dans l'appel ToDictionary. Vous pouvez facilement ajouter TryParse méthodes etc si vous le souhaitez.

Bien sûr, si vous avez besoin ce en un seul endroit, ne vous embêtez pas avec une classe séparée etc :)

+0

On dirait que c'est la meilleure façon de répondre à l'inverse de cette question: http://stackoverflow.com/questions/3392030/convert-a-xna-color-object-to-a-string –

7

Depuis l'OP mentionné dans un commentaire qu'il utilise Microsoft.Xna.Framework.Graphics.Color plutôt que System.Drawing.Color vous pouvez d'abord créer un System.Drawing.Color puis le convertir en un Microsoft.Xna.Framework.Graphics.Color

public static Color FromName(string colorName) 
{ 
    System.Drawing.Color systemColor = System.Drawing.Color.FromName(colorName); 
    return new Color(systemColor.R, systemColor.G, systemColor.B, systemColor.A); //Here Color is Microsoft.Xna.Framework.Graphics.Color 
} 
+0

La deuxième ligne devrait être: Couleur xnaColor = nouvelle couleur (systemColor.R, systemColor.G, systemColor.B, systemColor.A); Mais je crois que c'est la façon la plus simple d'accomplir ce que Robert a demandé. – Romias

+0

@Romias merci, corrigé. – Davy8

+0

... et une déclaration 'return' appropriée devrait être ajoutée aussi :) –

3

Cela a fonctionné bien pour mes besoins;) L'espoir que quelqu'un puisse l'utiliser ....

public static Color FromName(String name) 
    { 
     var color_props= typeof(Colors).GetProperties(); 
     foreach (var c in color_props) 
      if (name.Equals(c.Name, StringComparison.OrdinalIgnoreCase)) 
       return (Color)c.GetValue(new Color(), null); 
     return Colors.Transparent; 
    } 
3

Pour transférer des couleurs via des chaînes xml-je ai trouvé:

Color x = Color.Red; // for example 
String s = x.ToArgb().ToString() 
... to/from xml ... 
Int32 argb = Convert.ToInt32(s); 
Color red = Color.FromArgb(argb); 
2

La façon la plus simple:

string input = null; 
Color color = Color.White; 

TextBoxText_Changed(object sender, EventsArgs e) 
{ 
    input = TextBox.Text; 
} 

Button_Click(object sender, EventsArgs e) 
{ 
    color = Color.FromName(input) 
} 
5

Cela dépend de ce que vous cherchez, si vous besoin de System.Windows.Media.Color (comme dans WPF) c'est très simple:

System.Windows.Media.Color color = (Color)System.Windows.Media.ColorConverter.ConvertFromString("Red");//or hexadecimal color, e.g. #131A84