C++ Structures and Data Bindings
February 27, 2013
New York, N.Y.
As I was methodically converting all the Windows 8 C# code in Programming Windows, 6th edition to C++, it was always nice to come across one of the many programs in the book that do their thing entirely in XAML. Those projects didn't require any new C++ code and worked the same as the C# versions.
Well, not always. I have a nasty habit of using Color values and the Colors class to demonstrate ListBox and other controls that derive from ItemsControl to display collections. For example, here's some XAML in a C# project with seven Color values in a ListBox with an ItemTemplate that colors a Rectangle with the color and displays the RGB values:
<Page x:Class="CsColorList.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CsColorList">
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<ListBox>
<Color>Red</Color>
<Color>Orange</Color>
<Color>Yellow</Color>
<Color>Green</Color>
<Color>Blue</Color>
<Color>Indigo</Color>
<Color>Violet</Color>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0"
Width="48"
Height="48"
Margin="12">
<Rectangle.Fill>
<SolidColorBrush Color="{Binding}" />
</Rectangle.Fill>
</Rectangle>
<StackPanel Grid.Column="1"
Orientation="Horizontal"
VerticalAlignment="Center">
<TextBlock Text="{Binding R}" />
<TextBlock Text="," />
<TextBlock Text="{Binding G}" />
<TextBlock Text="," />
<TextBlock Text="{Binding B}" />
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Page>
And here's what it looks like:
Now let's put that same XAML (with the exception of a different project name) in a C++ project:
<Page x:Class="CppColorList.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CppColorList">
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<ListBox>
<Color>Red</Color>
<Color>Orange</Color>
<Color>Yellow</Color>
<Color>Green</Color>
<Color>Blue</Color>
<Color>Indigo</Color>
<Color>Violet</Color>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0"
Width="48"
Height="48"
Margin="12">
<Rectangle.Fill>
<SolidColorBrush Color="{Binding}" />
</Rectangle.Fill>
</Rectangle>
<StackPanel Grid.Column="1"
Orientation="Horizontal"
VerticalAlignment="Center">
<TextBlock Text="{Binding R}" />
<TextBlock Text="," />
<TextBlock Text="{Binding G}" />
<TextBlock Text="," />
<TextBlock Text="{Binding B}" />
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Page>
Now it looks like this:
The colors are fine but the RGB values are gone! What happened?
In a Windows 8 application written in C#, the Color structure is very similar to the Color structure in Silverlight and Windows Phone. It has properties named A, R, G, and B, some instance methods, and a static method called FromArgb that creates a Color value from the four separate values.
The Color structure is a little different in C++. In C++ the application perceives this structure as if it were defined like this:
public value struct Color
{
uint8 A;
uint8 R;
uint8 G;
uint8 B;
};
The four values are fields rather than properties, and that's why the bindings don't work. In Windows 8, data bindings only work with properties.
Notice that Color is defined as a value struct rather than a plain old struct. This type is part of the extensions to C++ (the "CX" in C++/CX) that were introduced for Windows 8. A value struct is for objects that are always passed around by value, and there are severe restrictions on the members of such a type: All fields in a value struct must be public, and all members that are not fields must be private. The value struct is very similar to what in C++ is called a POD ("plain old data") structure, and it's useful in situations where you don't want a structure encumbered with any baggage such as a vtable, which would be required if it were allowed to have public or protected methods.
Other prominent value struct structures in the Windows Runtime are Point, Rect, Size, Duration, Thickness, Matrix, and some others.
For some of these structures, there are accompanying "helper" classes that compensate for the lack of methods in the structure itself. For example, the ColorHelper class has a static FromArgb method that does the same thing as the static FromArgb method of the C# Color structure.
So what do you do if you want to put Color values in an items control and display their RGB values? One solution is to wrap the Color structure in your own class. In Chapter 11 of my book, I define a class called NamedColor that uses reflection to generate all the individual Color values defined in the Colors class and expose the color name as well as the actual value. In the C# version of this class, the Color value is a public property; in the C++ version I made the individual A, R, G, and B values public properties as well so the bindings work.
The C# version of the NamedColor class also has a public static property named All of type IEnumerable<NamedColor> that can simply be bound to the ItemsSource property of a ListBox or other ItemsControl derivative. But when converting that class to C++, I discovered that a binding to a static property does not work in a C++ project.
I'm sure there's a good explanation for that one, but I don't know what it is.