Introduction
I was creating an application that was displaying on a graph a number of different items, and I wanted to visually differentiate these items by their text.
Background
If you've not used XAML Converters before then in simple terms, they are class that implements the IValueConverter interface. This interface has two methods Convert and ConvertBack. The methods take an object of one type and convert it to another. This class can then be added as a resource to your XAML markup and used in any binding.
See this MSDN article for more information.
Using the code
The class is straight forward and looks like:
using System;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Data;
using System.Windows.Media;
public class StringToBrushConverter : IValueConverter
{
public object Convert(object value, Type targetType
, object parameter, System.Globalization.CultureInfo culture)
{
if (value != null && value is string)
{
string text = (string) value;
byte[] data;
using (MD5 md5 = MD5.Create())
data = md5.ComputeHash(Encoding.UTF8.GetBytes(text));
return new SolidColorBrush(
Color.FromArgb(180, data[0], data[7], data[15]));
}
return new SolidColorBrush(Color.FromRgb(255, 255, 255));
}
public object ConvertBack(object value, Type targetType
, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
After some checks that your passed object is a string, we calculate a MD5 hash of the string and pick 3 random values from that hash (the data[0], data[7] and data[15]) to create a new brush.
If you're asking why? That's reasonable, this wasn't my first solution, I started with what probably everyone would start with, converting the string to their ASCII codes. And yes this works, but there's a fairly massive issue...consider strings that almost the same (e.g. DataItem5, DataItem16) with the ASCII method you'll end up with colours that are pretty much indistinguishable. The reason is for most text your using around 90 values and you're mapping that to a pool of 2,147,483,947 possible colours.
If you want to use this approach in a Windows Forms or ASP or anywhere else, then you only need the code within the if block, and then just return the Color rather than the XAML SolidColorBrush object.
Points of Interest
Is there a less computationally expensive method of achieving the same thing?
Could you ever implement the ConvertBack method? :D
History
1st and hopefully only version:)