Introduction
I wanted a way to convert string names into colors and brushes. This small sample provides the ability to present names as hexadecimal, color name, or system color names.
Background
The built in markup extensions allow converting from hexadecimal or named color to brushes. I wanted a unified way to also include system colors. More specifically I wanted to be able to convert a string representation of a hexadecimal, color, or system color name into a real color and then extend that to allow markup to support conversion to a brush.
Using the code
The heart of the project is a module called NamedColors. It has the following routines:
- AllNames returns a list of all known color names.
- Names returns a list of the named colors
- SystemNames returns a list of system color names
- FromName takes a string value and if possible returns a
System.Windows.Media.Color
value. If it fails it returns Nothing
. The color name is case insensitive and may contain spaces. For example: aliceblue, Hot track color, AZURE, and #ff 80 ff 80 are all valid colors.
- IsValid takes a string value and indicates if the value can be converted to a color.
Also included is a markup extension called NamedColor
that returns a solid brush based on the name provided. To use the markup extension you must have a namespace reference to your project. In the example project the following reference is used:
xmlns:app="clr-namespace:NamedColors"
Following are some examples of using the markup extension:
<Label Background="{app:NamnedColor Name='#ff 80 ff 80'}" />
<Label Background="{app:NamedColor Name=aliceblue}" />
<Label Background="{app:NamedColor Name=hottrackcolor}" />
The example application demonstrates three ways of using the code.
- In the text box you can enter a value. The label immediately to the right will display the color if valid or a red ! if invalid.
- The next label displays a value using the markup extension.
- The bottom of the screen has a list box. Select a color from the list box and see a preview of that color to the left. The first 18 values are sample values followed by all the named and system colors.
Points of Interest
When writing the code two interesting problems presented themselves. First, Colors And SystemColors is not an enum. To get the color names I had to iterate over the properties.
For Each prop As System.Reflection.PropertyInfo In GetType(Colors).GetProperties()
If prop.PropertyType.FullName = "System.Windows.Media.Color" Then
_name.Add(prop.Name, prop.Name)
_all.Add(prop.Name, prop.Name)
End If
Next prop
Second, to retrieve the actual color I had to determine which type of conversion to try while attempting to minimize the number of errors that might be thrown.
Public Function FromName(name As String) As System.Windows.Media.Color?
If InStr(name, " ") > 0 Then name = Replace(name, " ", "")
If _all.ContainsKey(name) Then name = _all(name)
If _sys.ContainsKey(name) Then
Dim prop = GetType(SystemColors).GetProperty(name)
Return prop.GetValue(Nothing)
ElseIf _name.ContainsKey(name) OrElse name(0) = "#" Then
Try
Return ColorConverter.ConvertFromString(name)
Catch ex As Exception
End Try
End If
Return Nothing
End Function