There is a column in the Lines ListView of the Edit Model dialog box of the GeometryViz3D tool for the user to choose the color of the lines. Previously the colors are shown as plain text in the ComboBoxes. It will be more user friendly if the colors can be illustrated as the actual colors as shown in the following screen shot.
Here is the XAML code I use to achieve this. The key idea is customize the ItemTemplate of the ComboBoxes bound to the Color column of the Lines ListView by drawing a Rectangle.
The ItemSource property of the ComboBox is bound to the Colors property of the EditModelViewModel object, which is an array of strings that are color names, including Black, Cyan, and so on. And therefore, each item of the ComboBox is bound to the name of a color. We bind the color name to the Fill property of the Rectangle by taking advantage of the WPF’s built-in feature that converts a color name to a Brush.
The remaining issue is how to specify the size of the Rectangle. If we don’t specify, the actual height and width will both be 0. After some research using the snoop tool, I decided to determine the Height based on the FontSize of the ComboBox, and the Width based on the ActualWidth the ComboBox. Since the ComboBox is an ancestor of the items of the drop down list, we use the ComboBox as the RelativeSource. To make the Height of the ComboBox similar to the ComboBoxes in other columns, we have to adjust the value a little bit. This is where the DoubleAdditionConverter comes in. We make the Height to be FontSize + 2, and Width to be ActualWidth – 4.
Since the Height and Width of the Rectangle will not change after initialized, we set the binding Mode to OneTime.
The SelectedValue property of the ComboBox is bound to the Color property of the G3DLine object that is bound to the ListViewItem.
<Window.Resources> <local:DoubleAdditionConverter x:Key="doubleAdditionConverter" /> … <DataTemplate x:Key="colorCellTemplate"> <ComboBox ItemsSource="{Binding Colors}" SelectedValue="{Binding Color}" Margin="-6, 0, -6, 0" > <ComboBox.ItemTemplate> <DataTemplate> <Rectangle Fill="{Binding Mode=OneTime}" Height="{Binding Mode=OneTime, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ComboBox}}, Path=FontSize, Converter={StaticResource doubleAdditionConverter}, ConverterParameter=2}" Width="{Binding Mode=OneTime, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ComboBox}}, Path=ActualWidth, Converter={StaticResource doubleAdditionConverter}, ConverterParameter=-4}" /> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox> </DataTemplate> </Window.Resources> <ListView Margin="3" ItemsSource="{Binding Lines}" SelectedValue="{Binding SelectedLine}"> <ListView.View> <GridView> <GridView.Columns> … <GridViewColumn Header="Color" Width="120" CellTemplate="{StaticResource colorCellTemplate}" /> </GridView.Columns> </GridView> </ListView.View> </ListView>
Here is the source code of the DoubleAdditionConverter:
public class DoubleAdditionConverter : IValueConverter { #region IValueConverter Members public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { double v = (double)value; double p = Double.Parse((string)parameter); return v + p; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { double v = (double)value; double p = Double.Parse((string)parameter); return v - p; } #endregion }
The entire source code can be found at the GeometryViz3D project on CodePlex.
Leave a comment