A simple list of colors is reasonably straightforward using a little Reflection:
public List<string> SimpleColorList
{
get
{
List<string> colorList = new List<string>();
foreach (PropertyInfo pi in typeof(Colors).GetProperties())
{
colorList.Add(pi.Name);
}
return colorList;
}
}
And bound it to a ComboBox. Using Mode=OneTime means the ColorList is only built once.<ComboBox ItemsSource="{Binding Path=SimpleColorList, Mode=OneTime}"
SelectedValue="{Binding SelectedColor}"
Width="200" />
Adding a ItemTemplate to the ComboBox makes it a little more interesting:<ComboBox ItemsSource="{Binding Path=SimpleColorList, Mode=OneTime}"
SelectedValue="{Binding SelectedColor}"
Width="200">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Width="130"
Text="{Binding}" />
<Border BorderBrush="Black"
BorderThickness="1"
CornerRadius="4"
Margin="0,1,0,1"
Background="{Binding}"
Width="40"
Height="18">
</Border>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
The straight alphabetic sorted list is fine but I wanted to sort by "color", in general terms from lighter to darker. I found some code on the web that would convert the RGB into the HSL color space. (I'm afraid I can't find the code again so my apologies to its author for the lack of attribution). public static class HslValueConverter
{
/// <summary>
/// Converts a WPF RGB color to an HSL color
/// </summary>
/// <param name="rgbColor">The RGB color to convert.</param>
/// <returns>An HSL color object equivalent to the RGB color object passed in.</returns>
public static HslColor RgbToHsl(string name, Color rgbColor)
{
// Initialize result
var hslColor = new HslColor();
hslColor.Name = name;
// Convert RGB values to percentages
double r = (double)rgbColor.R / 255;
var g = (double)rgbColor.G / 255;
var b = (double)rgbColor.B / 255;
var a = (double)rgbColor.A / 255;
// Find min and max RGB values
var min = Math.Min(r, Math.Min(g, b));
var max = Math.Max(r, Math.Max(g, b));
var delta = max - min;
/* If max and min are equal, that means we are dealing with
* a shade of gray. So we set H and S to zero, and L to either
* max or min (it doesn't matter which), and then we exit. */
//Special case: Gray
if (max == min)
{
hslColor.Hue = 0;
hslColor.Saturation = 0;
hslColor.Lightness = max;
return hslColor;
}
/* If we get to this point, we know we don't have a shade of gray. */
// Set L
hslColor.Lightness = (min max) / 2;
// Set S
if (hslColor.Lightness < 0.5)
{
hslColor.Saturation = delta / (max min);
}
else
{
hslColor.Saturation = delta / (2.0 - max - min);
}
// Set H
if (r == max) hslColor.Hue = (g - b) / delta;
if (g == max) hslColor.Hue = 2.0 (b - r) / delta;
if (b == max) hslColor.Hue = 4.0 (r - g) / delta;
hslColor.Hue *= 60;
if (hslColor.Hue < 0) hslColor.Hue = 360;
// Set A
hslColor.Alpha = a;
// Set return value
return hslColor;
}
}
public struct HslColor
{
public string Name { get; set; }
public double Alpha;
public double Hue;
public double Lightness;
public double Saturation;
}
Then I changed the property (Note: the property name has changed to SortedColorList, so the ComboBox Binding will have to be altered) "getter" to sort by Saturation, Hue and Lightness. I also decided to exclude the Transparent color. public List<string> SortedColourList
{
get
{
List<HslColor> colorList = new List<HslColor>();
foreach (PropertyInfo pi in typeof(Colors).GetProperties())
{
Color color = (Color)pi.GetValue(null, null);
// Only select non-Transparent colors
if (color.A != 0) colorList.Add(HslValueConverter.RgbToHsl(pi.Name, color));
}
return colorList.OrderBy(c => c.Saturation)
.OrderBy(c => c.Hue)
.OrderByDescending(c => c.Lightness)
.Select(c => c.Name).ToList<string>();
}
}
The SimpleColorPicker project is available on GoogleCode.
No comments:
Post a Comment