71

I am encountering a problem which is how do I convert input strings like "RED" to the actual Color type Color.Red in C#. Is there a good way to do this?

I could think of using a switch statement and cases statement for each color type but I don't think that is clever enough.

Kevin
  • 6,711
  • 16
  • 60
  • 107

10 Answers10

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

The MSDN doesn't say one way or another, so there's a good chance that it is case-sensitive. (UPDATE: Apparently, it is not.)

As far as I can tell, ColorTranslator.FromHtml is also.

If Color.FromName cannot find a match, it returns new Color(0,0,0);

If ColorTranslator.FromHtml cannot find a match, it throws an exception.

UPDATE:

Since you're using Microsoft.Xna.Framework.Graphics.Color, this gets a bit tricky:

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);
James Curran
  • 101,701
  • 37
  • 181
  • 258
  • Hey James,thx for your comment.Since I am developing this in the XNA GameStudio,after I input your code,the program complains: Error 1 'Microsoft.Xna.Framework.Graphics.Color' does not contain a definition for 'FromName' and no extension method 'FromName' accepting a first argument of type 'Microsoft.Xna.Framework.Graphics.Color' could be found (are you missing a using directive or an assembly reference?) C:\Users\Guoguo\Desktop\MapWorld2\MapWorld\GameObject.cs 194 27 MapWorld Do you what the error is?Thanks. – Kevin Aug 02 '10 at 20:35
  • 3
    +1 for mentioning the different behavior when a match isn't found. – Davy8 Aug 02 '10 at 20:35
  • Microsoft.Xna.Framework is not the right namespace. Use System.Drawing – StingyJack Aug 02 '10 at 20:41
  • This is a method found in System.Drawing.Color, not (apparently) Microsoft.Xna.Framework.Graphics.Color. – Larsenal Aug 02 '10 at 20:41
  • 3
    @StingyJack: You can't ask the OP to change which type he's interested in! Admittedly it would have been nice to have been *told* what type he was interested in to start with... – Jon Skeet Aug 02 '10 at 20:44
  • The edit assumes the set of colors in `System.Drawing.Color` is the same as that in the XNA `Color` type. That may or may not be the case... and may or may not be important (the OP may be happy with the range of colors in `System.Drawing`). – Jon Skeet Aug 02 '10 at 20:56
  • Thanks all guys for your input! I got the Jame's final version of code working,and I will study two other methods posted. – Kevin Aug 02 '10 at 20:56
22
System.Drawing.Color myColor = System.Drawing.ColorTranslator.FromHtml("Red");

(Use my method if you want to accept HTML-style hex colors.)

Larsenal
  • 49,878
  • 43
  • 152
  • 220
15

(It would really have been nice if you'd mentioned which Color type you were interested in to start with...)

One simple way of doing this is to just build up a dictionary via reflection:

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

That will be relatively slow for the first lookup (while it uses reflection to find all the properties) but should be very quick after that.

If you want it to be case-insensitive, you can pass in something like StringComparer.OrdinalIgnoreCase as an extra argument in the ToDictionary call. You can easily add TryParse etc methods should you wish.

Of course, if you only need this in one place, don't bother with a separate class etc :)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Looks like this is the best way to answer the reverse of this question: http://stackoverflow.com/questions/3392030/convert-a-xna-color-object-to-a-string – Bennor McCarthy Aug 02 '10 at 23:17
12

It depends on what you're looking for, if you need System.Windows.Media.Color (like in WPF) it's very easy:

System.Windows.Media.Color color = (Color)System.Windows.Media.ColorConverter.ConvertFromString("Red");//or hexadecimal color, e.g. #131A84
pr0gg3r
  • 4,254
  • 1
  • 36
  • 27
8

Since the OP mentioned in a comment that he's using Microsoft.Xna.Framework.Graphics.Color rather than System.Drawing.Color you can first create a System.Drawing.Color then convert it to a 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
}
Davy8
  • 30,868
  • 25
  • 115
  • 173
  • The second line should be: Color xnaColor = new Color(systemColor.R, systemColor.G, systemColor.B, systemColor.A); But I belive this is the simplest way to accomplish what Robert asked. – Romias Aug 02 '10 at 20:53
  • ...and a proper `return` statement should be added too :) – Peter Lillevold Aug 02 '10 at 23:00
5

For transferring colors via xml-strings I've found out:

Color x = Color.Red; // for example
String s = x.ToArgb().ToString()
... to/from xml ...
Int32 argb = Convert.ToInt32(s);
Color red = Color.FromArgb(argb);
LarsTech
  • 80,625
  • 14
  • 153
  • 225
user2457260
  • 61
  • 1
  • 1
3

This worked nicely for my needs ;) Hope someone can use it....

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

The simplest way:

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)
}
Gustaf
  • 21
  • 1
  • 6
1

The following can generate a color from name, hex, or known name.

Color beige = StringToColor("Beige");
Color purple = StringToColor("#800080");
Color window = StringToColor("Window");

public static Color StringToColor(string colorStr)
{
    TypeConverter cc = TypeDescriptor.GetConverter(typeof(Color));
    var result = (Color)cc.ConvertFromString(colorStr);
    return result;
}

The snippet was taken from Jo Albahari's C# in a Nutshell.

Fidel
  • 7,027
  • 11
  • 57
  • 81
  • `System.NotSupportedException: 'TypeConverter cannot convert from System.String.'` is what I get when I try this – GuidoG Dec 27 '22 at 08:05
-2

I've used something like this before:

        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;
    }
Skyler
  • 341
  • 2
  • 10
  • @Jon I got mixed up with ConsoleColor. The same logic could still apply though... right? Instead of Enum.Parse() he can do a case insensitive compare on property names and return the result. (obviously removing the IsEnum check). – Skyler Aug 02 '10 at 20:48
  • I think finding the property by reflection each time would be relatively painful. Better, IMO, to build a dictionary once (as per my answer). – Jon Skeet Aug 02 '10 at 20:55
  • @Jon Yeah I saw it after I refreshed. – Skyler Aug 02 '10 at 21:00