ColorPicker на WPF


Нашел статейку (http://www.codeproject.com/KB/WPF/WPF_CustomerControl.aspx) про то как делать собственные контролы на WPF. Если не придираться к использованию терминов и формулировкам, то с приведенным способом написания своих контролов можно согласиться. А вот выбранный пример абсолютно неадекватен, т.к. ColorPicker в WPF можно сделать гораздо проще и быстрее с помощью DataTemplate.
ColorPicker на WPF

Итак, для начала кинем на окно ListBox и сделаем так, чтобы ListBoxItems в листбоксе были расположены не по вертикали, а по горизонтали и переносились при достижении конца строки, для этого укажем, что вместо стандартной StackPanel в ListBox будет использоваться WrapPanel:
<ListBox Name="colorsListBox" HorizontalAlignment="Center" Width="200" ItemTemplate="{StaticResource ColorTemplate}" SelectionChanged="OnNewColorSelected" SelectedIndex="1" Margin="0,0,0,21">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel IsItemsHost="True" Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollContentPresenter}}}"/>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
    </ListBox>

Теперь создадим DataTemplate для отображения цвета:

<DataTemplate x:Key="ColorTemplate">
    <Grid Width="15" Height="15" Margin="0,2,2,2" ToolTip="{Binding}" Background="#00000000">
<Rectangle Margin="0,0,0,0" Stroke="Black">
<Rectangle.Fill>
<SolidColorBrush Color="{Binding}"/>
</Rectangle.Fill>
</Rectangle>
<Rectangle Margin="0,0,0,0" Stroke="#00000000">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#00FFFFFF" Offset="0.692"/>
<GradientStop Color="#BFFFFFFF" Offset="1"/>
<GradientStop Color="#FFFFFFFF" Offset="0"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</DataTemplate>   

Осталась самая малость - задать список цветов и написать обработчик для выбора цвета. Список цветов можно задать двумя способами, в коде:

colorsListBox.ItemsSource = new Color[]{Colors.White,Colors.Blue,Colors.Red};

и в xaml-е:
<ListBox.ItemsSource>
    <x:Array Type="{x:Type Color}">
        <Color A="255" R="255" G="255" B="255"/>
        <Color>Blue</Color>
        <Color>Red</Color>
        <Color>Black</Color>
        <Color>Cyan</Color>
        <Color>Magenta</Color>
        <Color>Orange</Color>
        <Color>Pink</Color>
        <Color>Yellow</Color>
        <Color>Gold</Color>
        <Color>Gray</Color>
        <Color>Green</Color>
        <Color>Indigo</Color>
        <Color>Khaki</Color>
    </x:Array>
</ListBox.ItemsSource>

А обработчик выбора цвета вешается на SelectionChanged листбокса, например такой:

private void OnNewColorSelected(object sender, SelectionChangedEventArgs e)
{
    (LayoutRoot.Background as GradientBrush).GradientStops[1].Color = (Color)colorsListBox.SelectedItem;
}

Вот и все простой ColorPicker готов. Естественно все то, что я сейчас понаписал прямо в окне следует вынести в отдельный стиль и просто подключать его всякий раз, когда вам нужен выбор цветов.

Скачать исходники:


PS. А теперь об упомянутой в начале статье: в ней используется термин Custom Control, что неверно ибо в терминологии WPF это User Control - т.е. контрол с заданым внешним видом, тогда как Custom Control - это lookless контрол, т.е. не имеющий фиксированного внешнего вида, а использующий стили.

КОММЕНТАРИИ


НОВЫЙ КОММЕНТАРИЙ


*жирный*
_курсив_
+подчеркнутый+
! заголовок 1
!! заголовок 2
* список
** список 2
# нумерованый список
## нумерованый список 2
[url:http://www.example.com]
{"без форматирования"}
Полное описание синтаксиса