天天看點

[UWP]新控件ColorPicker

原文: [UWP]新控件ColorPicker

1. 前言

Fall Creators Update中提供了一個新得ColorPicker控件,解決了以前選擇顔色隻能用Combo Box的窘境。

2. 一個簡單的例子

<ColorPicker x:Name="ColorPicker"
             Margin="5" />

<Grid Margin="5">
    <Grid.Background>
        <SolidColorBrush Color="{x:Bind ColorPicker.Color, Mode=OneWay}" />
    </Grid.Background>
    <TextBlock Text="{x:Bind ColorPicker.Color}" />
</Grid>           
[UWP]新控件ColorPicker

如上所示,ColorPiker可以通過在光譜或色輪上拖動滑塊,或者在RGB/HSV及十六進制的TextBox中直接輸入顔色的數值改變Color屬性。

3. 定制ColorPicker

ColorPicker提供了很多屬性以設定它的外觀,下面介紹一些常用的屬性。

3.1 ColorSpectrumShape

ColorSpectrumShape是定義ColorPicker外觀的主要屬性。當設定為

ColorSpectrumShape.Box

時顯示正方形的光譜,設定為

ColorSpectrumShape.Ring

時顯示為圓型的HSV色輪。

3.2 最簡化顯示

完整的ColorPicker實在太占空間,而且整個控件左邊高右邊低,很不平衡。使用以下設定可以隐藏ColorPreview及其它Text Box以最簡化ColorPicker的顯示,使它勉強正常一點。

<ColorPicker x:Name="ColorPicker"
             ColorSpectrumShape="Ring"
             IsColorPreviewVisible="False"
             IsColorChannelTextInputVisible="False"
             IsHexInputVisible="False" />
           
[UWP]新控件ColorPicker

3.3 其它屬性

使用如下XAML基本可以将所有元素顯示出來:

<ColorPicker x:Name="ColorPicker"
         IsColorPreviewVisible="True"
         IsAlphaEnabled="True"
         IsMoreButtonVisible="True"/>
           
[UWP]新控件ColorPicker

下面清單列出了各元素對應的屬性。

[UWP]新控件ColorPicker

4. 封裝ColorPicker

ColorPicker難用的地方在于它是個大塊頭,而且沒有Header,擺在表單裡面格格不入。官方文檔裡面還介紹了怎麼把ColorPicker放在Button的Flyout裡使用,都做到這樣了還不如直接提供這個彈出控件。

為了使它更好用我把它簡單地封裝到一個彈出控件中。由于Picker控件通常都是指點選按鈕彈出一個Popup或Flyout通過滑鼠點選選擇值的控件,例如DatePicker、TimePicker或者Extended WPF Toolkit 中的ColorPicker,UWP中的ColorPicker這個名稱讓我很為難,隻好把自己封裝的控件命名為ColorSelector。詳細代碼請見文章最後給出的Fluent Design System Sample源碼。

<Style TargetType="local:ColorSelector">
    <Setter Property="IsTabStop"
            Value="False" />
    <Setter Property="FontFamily"
            Value="{ThemeResource ContentControlThemeFontFamily}" />
    <Setter Property="FontSize"
            Value="{ThemeResource ControlContentThemeFontSize}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:ColorSelector">
                <StackPanel x:Name="LayoutRoot"
                            Margin="{TemplateBinding Padding}">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal" />
                            <VisualState x:Name="Disabled">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderContentPresenter"
                                                                   Storyboard.TargetProperty="Foreground">
                                        <DiscreteObjectKeyFrame KeyTime="0"
                                                                Value="{ThemeResource DatePickerHeaderForegroundDisabled}" />
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                        <VisualStateGroup x:Name="PopupStates">
                            <VisualState x:Name="PopupOpened" />
                            <VisualState x:Name="PopupClosed" />
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <local:HeaderedContentControl Header="{TemplateBinding Header}"
                                                  HeaderTemplate="{TemplateBinding HeaderTemplate}">
                        <ToggleButton x:Name="DateButton"
                                      DataContext="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=Color}"
                                      IsEnabled="{TemplateBinding IsEnabled}"
                                      IsChecked="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=IsDropDownOpen,Mode=TwoWay}"
                                      HorizontalAlignment="Stretch"
                                      HorizontalContentAlignment="Stretch">
                            <ToggleButton.Content>
                                    <Grid>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="Auto" />
                                            <ColumnDefinition />
                                        </Grid.ColumnDefinitions>
                                        <TextBlock Text="Select A Color:" />
                                        <Rectangle Grid.Column="1"
                                                   Margin="5,0,0,0">
                                            <Rectangle.Fill>
                                                <SolidColorBrush Color="{Binding}" />
                                            </Rectangle.Fill>
                                        </Rectangle>
                                    </Grid>
                                </ToggleButton.Content>
                            <FlyoutBase.AttachedFlyout>
                                <Flyout Placement="Bottom"
                                        x:Name="Flyout">
                                    <Flyout.FlyoutPresenterStyle>
                                        <Style TargetType="FlyoutPresenter">
                                            <Setter Property="Padding"
                                                    Value="0" />
                                            <Setter Property="BorderThickness"
                                                    Value="0" />
                                            <Setter Property="Template">
                                                <Setter.Value>
                                                    <ControlTemplate TargetType="FlyoutPresenter">
                                                        <ContentPresenter Background="{TemplateBinding Background}"
                                                                          BorderBrush="{TemplateBinding BorderBrush}"
                                                                          BorderThickness="{TemplateBinding BorderThickness}"
                                                                          Content="{TemplateBinding Content}"
                                                                          ContentTemplate="{TemplateBinding ContentTemplate}"
                                                                          ContentTransitions="{TemplateBinding ContentTransitions}"
                                                                          Margin="{TemplateBinding Padding}"
                                                                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                                                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                                                    </ControlTemplate>
                                                </Setter.Value>
                                            </Setter>
                                        </Style>
                                    </Flyout.FlyoutPresenterStyle>
                                    <Grid>
                                        <Grid.RowDefinitions>
                                            <RowDefinition />
                                            <RowDefinition Height="Auto" />
                                        </Grid.RowDefinitions>
                                        <ColorPicker x:Name="ColorPicker"
                                                     Style="{TemplateBinding ColorPickerStyle}"
                                                     IsColorPreviewVisible="False"
                                                     IsColorChannelTextInputVisible="False"
                                                     IsHexInputVisible="False" />
                                        <Grid Grid.Row="1"
                                              Height="45"
                                              x:Name="AcceptDismissHostGrid">
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="*" />
                                                <ColumnDefinition Width="*" />
                                            </Grid.ColumnDefinitions>
                                            <Rectangle Height="2"
                                                       VerticalAlignment="Top"
                                                       Fill="{ThemeResource DatePickerFlyoutPresenterSpacerFill}"
                                                       Grid.ColumnSpan="2" />
                                            <Button x:Name="AcceptButton"
                                                    Grid.Column="0"
                                                    Content="&#xE8FB;"
                                                    FontFamily="{ThemeResource SymbolThemeFontFamily}"
                                                    FontSize="16"
                                                    HorizontalAlignment="Stretch"
                                                    VerticalAlignment="Stretch"
                                                    Style="{StaticResource DateTimePickerFlyoutButtonStyle}"
                                                    Margin="0,2,0,0" />
                                            <Button x:Name="DismissButton"
                                                    Grid.Column="1"
                                                    Content="&#xE711;"
                                                    FontFamily="{ThemeResource SymbolThemeFontFamily}"
                                                    FontSize="16"
                                                    HorizontalAlignment="Stretch"
                                                    VerticalAlignment="Stretch"
                                                    Style="{StaticResource DateTimePickerFlyoutButtonStyle}"
                                                    Margin="0,2,0,0" />
                                        </Grid>
                                    </Grid>
                                </Flyout>
                            </FlyoutBase.AttachedFlyout>
                        </ToggleButton>
                    </local:HeaderedContentControl>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
           
[UWP]新控件ColorPicker

(也許是Flyout沒有添加陰影或邊框的原因,看起來醜醜的。)

5. 結語

Winform中有ColorDialog:

[UWP]新控件ColorPicker

WPF有Extended WPF Toolkit 中的ColorPicker:

[UWP]新控件ColorPicker

而UWP拖到現在才終于肯提供一個ColorPicker。每次更新技術都扔掉一些常用控件,導緻開發者隻能選擇第三方控件或自己實作,連TreeView都是拖了幾年才搞出來。這難道是微軟對我們的考驗嗎?

5. 參考

Color Picker ColorPicker Class

6. 源碼

Fluent Design System Sample XamlUIBasics