private Color GetColorFromString(string input)
{
Type colorClass = typeof(Colors);
List<MethodInfo> colorMethods = new List<MethodInfo>(colorClass.GetMethods());
foreach (MethodInfo info in colorMethods)
{
string methodName = info.Name;
if (info.Name.StartsWith("get_"))
{
string actualColor = info.Name.Split('_')[1];
if (String.Compare(input, actualColor, true) == 0)
{
// We have a match!
return (Color)info.Invoke(null, null);
}
}
}
return Colors.Black;
}
This method will take any color that is in the Colors object, and return the appropriate color. (If someone knows an easier way to do this, I'd love to hear it). You will need to add System.Windows.Media, System.Windows.Data and System.Reflection to use my method. If you want more info on the Colors class, take a look at: http://msdn2.microsoft.com/en-us/library/system.windows.media.colors.aspx
Ok, so now with this, we're going to modify our VC one more time, to allow it to take three arguments. My plan is to go through the arguments one at a time, check to see if our input is greater then the first, if so, return the color, if not, go on to the second. I'm actually going to ignore the first piece of the final argument, since it will simply end up as the default. I'm going to seperate the arguments with ';', and individual pieces with a ':'. So, here's the new code:
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
try
{
string paramAsString = parameter.ToString();
string[] splitParam = paramAsString.Split(';');
string[] firstArgument = splitParam[0].Split(':');
string[] secondArgument = splitParam[1].Split(':');
string[] thirdArgument = splitParam[2].Split(':');
double firstInterval = System.Convert.ToDouble(firstArgument[0]);
Color firstColor = this.GetColorFromString(firstArgument[1]);
double secondInterval = System.Convert.ToDouble(secondArgument[0]);
Color secondColor = this.GetColorFromString(secondArgument[1]);
Color thirdColor = this.GetColorFromString(thirdArgument[1]);
double inputValue = System.Convert.ToDouble(value);
if (inputValue >= firstInterval)
{
return new SolidColorBrush(firstColor);
}
else if (inputValue >= secondInterval)
{
return new SolidColorBrush(secondColor);
}
else
{
return new SolidColorBrush(thirdColor);
}
}
catch (Exception e)
{
return new SolidColorBrush(Colors.White);
}
}
If you give THIS one a try, set the parameter to something like: 95:Azure;10:Coral;0:SeaGreen. Now we've got a VC that you can configure all three brackets, as well as the colors that go with them.
Of course, this is hideously inelegant, so I want to make one last change. Instead of hard coding and breaking the parameters apart this way, I'm going to just create a loop. This will tighten up the code, and actually allow us to go an arbitrary number of brackets. So, if you need to have 15 different brackets of different colors from Indigo to MintCream, you can do it. So, we'll pull those ugly "secondParameter" lines out, and replace it with a foreach. (I've included the entire class here, in case you want to cut and paste)
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Data;
using System.Windows.Media;
using System.Reflection;
namespace ValueConverters
{
class FullyVariableVC : IValueConverter
{
private Color GetColorFromString(string input)
{
Type colorClass = typeof(Colors);
List<MethodInfo> colorMethods = new List<MethodInfo>(colorClass.GetMethods());
foreach (MethodInfo info in colorMethods)
{
string methodName = info.Name;
if (info.Name.StartsWith("get_"))
{
string actualColor = info.Name.Split('_')[1];
if (String.Compare(input, actualColor, true) == 0)
{
// We have a match!
return (Color)info.Invoke(null, null);
}
}
}
return Colors.Black;
}
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
try
{
string paramAsString = parameter.ToString();
string[] splitParam = paramAsString.Split(';');
double inputValue = System.Convert.ToDouble(value);
foreach (string bracket in splitParam)
{
string[] bracketParameters = bracket.Split(':');
Double bracketLimit;
try
{
bracketLimit = System.Convert.ToDouble(bracketParameters[0]);
}
catch (InvalidCastException)
{
return this.GetColorFromString(bracketParameters[1]);
}
if (inputValue >= bracketLimit)
{
return new SolidColorBrush(this.GetColorFromString(bracketParameters[1]));
}
}
}
catch (Exception e)
{
return new SolidColorBrush(Colors.White);
}
return new SolidColorBrush(Colors.White);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new Exception("The method or operation is not implemented.");
}
#endregion
}
}
Give this one a fly, and set the parameter to: 95:Azure;75:HotPink;40:Blue;10:Coral;-9999:Orange.
Enjoy :).
(As always, code here is provided "As-is" with no warranty, implied or otherwise. Use at your own risk)