Tuesday, 9 March 2010

Silverlight Hex color string and CSS style color string to C# Color structure converter

Unlike the full version of .Net there is no built in way of converting a string representation of a color into a color object in Silverlight.

There are many reasons you might need this bit of functionality,  the obvious one being able to pass a color parameter into a Silverlight app from it hosted web page.

Many people have had to tackle this in the last two years and there are plenty of examples on the web, but most just do hex strings in one format.

I wanted a color string converter that could handle all the CSS color formats. e.g. #FFFFFF, #FFF, white.

So the C# code below is a bit longer than most of the examples on the web, but it does a lot more......

Examples of how to use

Color c = TWSilverlightUtilities.ColorFromString("FFAABBCCDD");
Color c = TWSilverlightUtilities.ColorFromString("#F29");
Color c = TWSilverlightUtilities.ColorFromString("AliceBlue");


    public static class TWSilverlightUtilities
    {
        /// <summary>
        /// Converts a CSS style string into Color structure. Returns black if the input is invalid.
        /// </summary>
        /// <param name="value">The color string to convert. May be in one of the following formats; #FFFFFFFF, #FFFFFF, #FFF, white. The # is optional.</param>
        /// <returns></returns>        
        public static Color ColorFromString(string value)
        {
            Color rv = new Color();
            try
            {
                rv = ColorFromStringEx(value);
            }
            catch
            {
            }
            return rv;
        }
        /// <summary>
        /// Converts a CSS style string into Color structure. Throws an exception if the input is invalid.
        /// </summary>
        /// <param name="value">The color string to convert. May be in one of the following formats; #FFFFFFFF, #FFFFFF, #FFF, white. The # is optional.</param>
        /// <returns></returns>                
        public static Color ColorFromStringEx(string value)
        {
            Color rv = new Color();
            // empty string check
            if ((value == null) || (value.Length == 0))
                throw new Exception("empty color string");
            // determine the format, try standard one first
            Match m1 = Regex.Match(value, @"^#?([A-F\d]{2})([A-F\d]{2})([A-F\d]{2})([A-F\d]{2})?", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
            if ((m1.Success) && (m1.Groups.Count == 5))
            {
                if (m1.Groups[4].Value.Length > 0) // includes alpha channel
                    rv = Color.FromArgb(Byte.Parse(m1.Groups[1].Value, Globalization.NumberStyles.HexNumber),
                                Byte.Parse(m1.Groups[2].Value, Globalization.NumberStyles.HexNumber),
                                Byte.Parse(m1.Groups[3].Value, Globalization.NumberStyles.HexNumber),
                                Byte.Parse(m1.Groups[4].Value, Globalization.NumberStyles.HexNumber));
                else // colors only
                    rv = Color.FromArgb(0xFF,
                                Byte.Parse(m1.Groups[1].Value, Globalization.NumberStyles.HexNumber),
                                Byte.Parse(m1.Groups[2].Value, Globalization.NumberStyles.HexNumber),
                                Byte.Parse(m1.Groups[3].Value, Globalization.NumberStyles.HexNumber));
            }
            else
            {
                // try the CSS 3 char format next
                Match m2 = Regex.Match(value, @"^#?([A-F\d])([A-F\d])([A-F\d])$", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
                if ((m2.Success) && (m2.Groups.Count == 4))
                {
                    byte r = Byte.Parse(m2.Groups[1].Value, Globalization.NumberStyles.HexNumber);
                    r += (byte)(r << 4);
                    byte g = Byte.Parse(m2.Groups[2].Value, Globalization.NumberStyles.HexNumber);
                    g += (byte)(g << 4);
                    byte b = Byte.Parse(m2.Groups[3].Value, Globalization.NumberStyles.HexNumber);
                    b += (byte)(b << 4);
                    rv = Color.FromArgb(0xFF,r,g,b);
                }
                else
                {
                    // This is the only way to access the colors that XAML knows about!
                    String xamlString = "<Canvas xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" Background=\"" + value + "\"/>";
                    Canvas c = (Canvas)System.Windows.Markup.XamlReader.Load(xamlString);
                    SolidColorBrush brush = (SolidColorBrush)c.Background;
                    rv = brush.Color;
                }
            }
            return rv;
        }
    }

1 comment: