Title: List colors in WPF and C#
This example shows how to list colors and display color samples in a WPF ListBox. To build the list, the example demonstrates reflection, LINQ, and XAML data templates.
The program uses the following XAML code to define the ListBox that will display the results.
<ListBox Name="lstColors">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0,3,0,0">
<StackPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="5,0,0,0"/>
</Style>
</StackPanel.Resources>
<Rectangle Width="30" Fill="{Binding SampleBrush}"/>
<TextBlock Width="130" Text="{Binding ColorName}"/>
<TextBlock Width="70" Text="{Binding HexValue}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The ListBox control's ItemTemplate property tells the ListBox how to display the items to which it is bound. The ItemTemplate must be set equal to a DataTemplate that describes the controls used to display data.
The DataTemplate can hold a single child, which in this example is a StackPanel. The StackPanel holds a Rectangle and two TextBlock objects.
The controls use bindings to set some of their properties equal to values that will be provided by the data objects bound to the ListBox. The code sets the Rectangle object's Fill property to the SampleBrush property provided by the data objects. Similarly the code sets the Text properties of the TextBlock objects to the data objects' ColorName and HexValue properties.
So where are the SampleBrush, ColorName, and HexValue properties defined? The program stores color information in the following ColorInfo class.
// Used to display color name, RGB value, and sample.
public class ColorInfo
{
public string ColorName { get; set; }
public Color Color { get; set; }
public SolidColorBrush SampleBrush
{
get { return new SolidColorBrush(Color); }
}
public string HexValue
{
get { return Color.ToString(); }
}
public ColorInfo(string color_name, Color color)
{
ColorName = color_name;
Color = color;
}
}
The class defines two auto-implemented properties ColorName and Color.
Important: The DataTemplate doesn't work if you bind it to fields instead of properties. For example, if you simply declare ColorName as a public string, then the DataTemplate can't find it so it displays nothing in its first TextBlock. (Try it and see what happens.) |
The class also defines two non-trivial read-only properties that return a SolidColorBrush that uses the object's color and the color's hex value as a string.
Finally the class provides a constructor to make initializing an object easier.
The last piece to the example is the following Window_Loaded event handler, which attaches data to the ListBox.
// List samples of the named colors.
private void Window_Loaded(object sender, RoutedEventArgs e)
{
var color_query =
from PropertyInfo property in typeof(Colors).GetProperties()
orderby property.Name
//orderby ((Color)property.GetValue(null, null)).ToString()
select new ColorInfo(
property.Name,
(Color)property.GetValue(null, null));
lstColors.ItemsSource = color_query;
}
This code creates a LINQ query that iterates over the results of typeof(Colors).GetProperties(). The GetProperties method returns an array of PropertyInfo objects that give information about the values defined by the Colors enumeration. (Using a type's GetProperties method is a form of reflection.)
The query orders the results by the colors' Name values. It selects new ColorInfo objects initialized by passing the constructor the colors' names and values. In this example, a PropertyInfo object represents a color so its GetValue method returns the Color that it represents. (Try replacing the orderby clause with the one that is commented out to see the colors sorted somewhat by their color components.)
The program then sets the ListBox control's ItemsSource property equal to the LINQ query. At that point, the control executes the query and iterates through the results, applying its DataTemplate to the objects selected by the query. As a result, the control lists colors defined by the Colors enumeration.
To summarize, the example uses these pieces:
- The ColorInfo class stores color information and provides the properties (not fields) the DataTemplate needs.
- The XAML code gives the ListBox an ItemTemplate containing a DataTemplate that contains the controls to display the data items. Properties values with the format {Binding PropertyName} use the data.
- The main program sets the ListBox control's ItemsSource to a list of data objects to display. (To build the list, the program uses a LINQ query that uses reflection.)
Download the example to experiment with it and to see additional details.
|