UWP:如何创建 "rounded" 颜色选择器

UWP: how to create a "rounded" color picker

我想创建一个看起来像 Windows Ink 的颜色选择器:

所以我创建了一个 GridView,其中包含我的 ItemTemplate:

<GridView x:Name="colorList2" HorizontalAlignment="Stretch" VerticalAlignment="Top" 
        IsItemClickEnabled="True" 
        ItemClick="colorList2_ItemClick" 
        SelectionMode="Single"
        SelectionChanged="colorList2_SelectionChanged"
        >
<GridView.ItemTemplate>
    <DataTemplate>
        <Grid RightTapped="Grid_RightTapped" Tapped="Grid_Tapped">
            <Button  Height="30" Width="30">
                <Button.Template>
                    <ControlTemplate TargetType="Button">
                        <Grid>
                            <Ellipse Fill="{Binding Color}"/>
                            <ContentPresenter Content="{TemplateBinding Content}" 
                                                HorizontalAlignment="Center" 
                                                VerticalAlignment="Center"/>
                        </Grid>
                    </ControlTemplate>
                </Button.Template>
            </Button>
        </Grid>
    </DataTemplate>
</GridView.ItemTemplate>

在 Grid_RightTapped 和 Grid_Tappent 事件中,我获得了点击的颜色,我为我的项目着色,并且我将所选项目影响到 GridView:

private void Grid_Tapped(object sender, TappedRoutedEventArgs e)
    {
        Colors selectedColor = (sender as Grid).DataContext as Colors;
        foreach (NodeViewModel node in diagram.Nodes as DiagramCollection<NodeViewModel>)
        {  
            ...
        }
        this.colorList2.SelectedItem = selectedColor;
    }
}

这很好用,但我想知道是否有办法 "customize" GridView 的 selected/hover 项的模板? 这些是正方形,我想用椭圆替换它们,就像 Windows Ink.

您需要为 GridViewItem 覆盖 ItemContainerStyle。 在C:\Program Files (x86)\WindowsKits\DesignTime\CommonConfiguration\Neutral\UAP中查看Generic.xaml中的GridViewItemExpanded样式.0.10240.0\Generic 并将 Rectangle 更改为 Ellipse。 并且不要忘记设置到您的 GridView。 例如:

<GridView>
    <GridView.ItemContainerStyle>
        <Style TargetType="GridViewItem">
            <!--Apply new data-->
        </Style>
    </GridView.ItemContainerStyle>
</GridView>

正确的样式是:

<GridView.ItemContainerStyle>
    <Style TargetType="GridViewItem">
        <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
        <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" />
        <Setter Property="TabNavigation" Value="Local"/>
        <Setter Property="IsHoldingEnabled" Value="True"/>
        <Setter Property="HorizontalContentAlignment" Value="Center"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="Margin" Value="0,2,12,12"/>
        <Setter Property="MinWidth" Value="0"/>
        <Setter Property="MinHeight" Value="0"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="GridViewItem">
                    <Grid x:Name="ContentBorder"
                        Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal">
                                    <Storyboard>
                                        <PointerUpThemeAnimation Storyboard.TargetName="ContentPresenter" />
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="PointerOver">
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="BorderRectangle"
                                                Storyboard.TargetProperty="Opacity"
                                                Duration="0"
                                                To="1"/>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderRectangle" Storyboard.TargetProperty="Stroke">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListLowBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualBlack" Storyboard.TargetProperty="Stroke">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <PointerUpThemeAnimation Storyboard.TargetName="ContentPresenter" />
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Pressed">
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="BorderRectangle"
                                                Storyboard.TargetProperty="Opacity"
                                                Duration="0"
                                                To="1"/>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderRectangle" Storyboard.TargetProperty="Stroke">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListMediumBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualBlack" Storyboard.TargetProperty="Stroke">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <PointerDownThemeAnimation TargetName="ContentPresenter" />
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Selected">
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="MultiSelectCheck"
                                                Storyboard.TargetProperty="Opacity"
                                                Duration="0"
                                                To="1"/>
                                        <DoubleAnimation Storyboard.TargetName="BorderRectangle"
                                                Storyboard.TargetProperty="Opacity"
                                                Duration="0"
                                                To="1"/>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderRectangle" Storyboard.TargetProperty="Stroke">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAccentBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualBlack" Storyboard.TargetProperty="Stroke">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectSquare" Storyboard.TargetProperty="Background">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAccentBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <PointerUpThemeAnimation Storyboard.TargetName="ContentPresenter" />
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="PointerOverSelected">
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="MultiSelectCheck"
                                                Storyboard.TargetProperty="Opacity"
                                                Duration="0"
                                                To="1"/>
                                        <DoubleAnimation Storyboard.TargetName="BorderRectangle"
                                                Storyboard.TargetProperty="Opacity"
                                                Duration="0"
                                                To="1"/>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderRectangle" Storyboard.TargetProperty="Stroke">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListAccentMediumBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualBlack" Storyboard.TargetProperty="Stroke">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectSquare" Storyboard.TargetProperty="Background">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAccentBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <PointerUpThemeAnimation Storyboard.TargetName="ContentPresenter" />
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="PressedSelected">
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="MultiSelectCheck"
                                                Storyboard.TargetProperty="Opacity"
                                                Duration="0"
                                                To="1"/>
                                        <DoubleAnimation Storyboard.TargetName="BorderRectangle"
                                                Storyboard.TargetProperty="Opacity"
                                                Duration="0"
                                                To="1"/>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderRectangle" Storyboard.TargetProperty="Stroke">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListAccentHighBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualBlack" Storyboard.TargetProperty="Stroke">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectSquare" Storyboard.TargetProperty="Background">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAccentBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <PointerDownThemeAnimation TargetName="ContentPresenter" />
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="DisabledStates">
                                <VisualState x:Name="Enabled"/>
                                <VisualState x:Name="Disabled">
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="ContentBorder"
                                                Storyboard.TargetProperty="Opacity"
                                                Duration="0"
                                                To="{ThemeResource ListViewItemDisabledThemeOpacity}"/>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="FocusStates">
                                <VisualState x:Name="Unfocused"/>
                                <VisualState x:Name="Focused">
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="FocusVisualWhite"
                                                Storyboard.TargetProperty="Opacity"
                                                Duration="0"
                                                To="1"/>
                                        <DoubleAnimation Storyboard.TargetName="FocusVisualBlack"
                                                Storyboard.TargetProperty="Opacity"
                                                Duration="0"
                                                To="1"/>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="MultiSelectStates">
                                <VisualState x:Name="MultiSelectDisabled">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectSquare" Storyboard.TargetProperty="Visibility">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="Visible" />
                                            <DiscreteObjectKeyFrame KeyTime="0:0:0.333" Value="Collapsed" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <FadeOutThemeAnimation TargetName="MultiSelectSquare"/>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="MultiSelectEnabled">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectSquare" Storyboard.TargetProperty="Visibility">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="Visible" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <FadeInThemeAnimation TargetName="MultiSelectSquare"/>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="DataVirtualizationStates">
                                <VisualState x:Name="DataAvailable"/>
                                <VisualState x:Name="DataPlaceholder"/>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="ReorderHintStates">
                                <VisualState x:Name="NoReorderHint"/>
                                <VisualState x:Name="BottomReorderHint">
                                    <Storyboard>
                                        <DragOverThemeAnimation TargetName="ContentBorder" ToOffset="{ThemeResource GridViewItemReorderHintThemeOffset}" Direction="Bottom" />
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="TopReorderHint">
                                    <Storyboard>
                                        <DragOverThemeAnimation TargetName="ContentBorder" ToOffset="{ThemeResource GridViewItemReorderHintThemeOffset}" Direction="Top" />
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="RightReorderHint">
                                    <Storyboard>
                                        <DragOverThemeAnimation TargetName="ContentBorder" ToOffset="{ThemeResource GridViewItemReorderHintThemeOffset}" Direction="Right" />
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="LeftReorderHint">
                                    <Storyboard>
                                        <DragOverThemeAnimation TargetName="ContentBorder" ToOffset="{ThemeResource GridViewItemReorderHintThemeOffset}" Direction="Left" />
                                    </Storyboard>
                                </VisualState>
                                <VisualStateGroup.Transitions>
                                    <VisualTransition To="NoReorderHint" GeneratedDuration="0:0:0.2"/>
                                </VisualStateGroup.Transitions>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="DragStates">
                                <VisualState x:Name="NotDragging" />
                                <VisualState x:Name="Dragging">
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="ContentBorder"
                                                Storyboard.TargetProperty="Opacity"
                                                Duration="0"
                                                To="{ThemeResource ListViewItemDragThemeOpacity}" />
                                        <DragItemThemeAnimation TargetName="ContentBorder" />
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="DraggingTarget">
                                    <Storyboard>
                                        <DropTargetItemThemeAnimation TargetName="ContentBorder" />
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="MultipleDraggingPrimary">
                                    <Storyboard>
                                        <!-- These two Opacity animations are required - the FadeInThemeAnimations
                                    on the same elements animate an internal Opacity. -->
                                        <DoubleAnimation Storyboard.TargetName="MultiArrangeOverlayBackground"
                                                Storyboard.TargetProperty="Opacity"
                                                Duration="0"
                                                To="1" />

                                        <DoubleAnimation Storyboard.TargetName="ContentBorder"
                                                Storyboard.TargetProperty="Opacity"
                                                Duration="0"
                                                To="{ThemeResource ListViewItemDragThemeOpacity}" />
                                        <FadeInThemeAnimation TargetName="MultiArrangeOverlayBackground" />
                                        <DragItemThemeAnimation TargetName="ContentBorder" />
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="MultipleDraggingSecondary">
                                    <Storyboard>
                                        <FadeOutThemeAnimation TargetName="ContentBorder" />
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="DraggedPlaceholder">
                                    <Storyboard>
                                        <FadeOutThemeAnimation TargetName="ContentBorder" />
                                    </Storyboard>
                                </VisualState>
                                <VisualStateGroup.Transitions>
                                    <VisualTransition To="NotDragging" GeneratedDuration="0:0:0.2"/>
                                </VisualStateGroup.Transitions>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <ContentPresenter x:Name="ContentPresenter"
                                ContentTransitions="{TemplateBinding ContentTransitions}"
                                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />

                        <Ellipse x:Name="MultiArrangeOverlayBackground"
                                IsHitTestVisible="False"
                                Opacity="0"
                                Fill="{ThemeResource ListViewItemDragBackgroundThemeBrush}"
                                Grid.ColumnSpan="2"/>
                        <Ellipse x:Name="BorderRectangle"
                                 Margin="-2"
                                 IsHitTestVisible="False"
                                 Stroke="{ThemeResource SystemControlHighlightListAccentLowBrush}"
                                 StrokeThickness="3"
                                 Opacity="0"/>
                        <Border x:Name="MultiSelectSquare"
                                Background="{ThemeResource SystemControlBackgroundChromeMediumBrush}"
                                Width="20"
                                Height="20"
                                Margin="0,2,2,0"
                                VerticalAlignment="Top"
                                HorizontalAlignment="Right"
                                Visibility="Collapsed" >
                            <FontIcon x:Name="MultiSelectCheck" 
                                      FontFamily="{ThemeResource SymbolThemeFontFamily}" 
                                      Glyph="&#xE73E;" 
                                      FontSize="16" 
                                      Foreground="{ThemeResource SystemControlForegroundBaseMediumHighBrush}" 
                                      Opacity="0"/>
                        </Border>
                        <Ellipse x:Name="FocusVisualWhite"
                        IsHitTestVisible="False"
                        Stroke="{ThemeResource SystemControlForegroundAltHighBrush}"
                        StrokeEndLineCap="Square"
                        StrokeDashArray="1.0, 1.0"
                        StrokeDashOffset="1.5"
                        StrokeThickness="2"
                        Opacity="0"/>
                        <Ellipse x:Name="FocusVisualBlack"
                        IsHitTestVisible="False"
                        Stroke="{ThemeResource SystemControlForegroundBaseHighBrush}"
                        StrokeEndLineCap="Square"
                        StrokeDashArray="1.0, 1.0"
                        StrokeDashOffset="0.5"
                        StrokeThickness="2"
                        Opacity="0"/>

                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</GridView.ItemContainerStyle>

这比你想象的要容易。

转到 https://msdn.microsoft.com/en-us/library/windows/apps/mt299122.aspx 找到 "GridViewItem styles and templates" 类别并输入它。

Select 并从此页面复制第二个样式(名为 x:Key="GridViewItemExpanded")

将其粘贴到您的部分。

按您喜欢的方式编辑并将您的 GridView 设置为 ItemContainerTemplate。

要得到椭圆而不是矩形,你只需要替换它 部分

<Rectangle x:Name="BorderRectangle" IsHitTestVisible="False"
                  Stroke="{ThemeResource SystemControlHighlightListAccentLowBrush}"
                  StrokeThickness="2"
                  Opacity="0"/>  

有了这个:

 <Ellipse x:Name="BorderRectangle" IsHitTestVisible="False"
                  Stroke="{ThemeResource SystemControlHighlightListAccentLowBrush}"
                  StrokeThickness="2"
                  Opacity="0"/>
  1. 随意编辑您想要的任何内容 - 您可能需要对样式中设置的所有矩形执行相同的操作。

编辑:Andrii Krupka 更快;)

我已经实现了与基本 XAML 控件类似的功能。留在这里以防有人觉得有用。

<RadioButton GroupName="HighilghterColors" x:Name="btn_GreenHighliter" IsChecked="True" MinWidth="40" Tag="green_highlighter">
    <RadioButton.Template>
        <ControlTemplate>
            <ToggleButton IsChecked="{Binding IsChecked, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" Padding="0" CornerRadius="50">
                <ToggleButton.Content>
                    <Ellipse Fill="LawnGreen" Width="29" Height="29"/>
                </ToggleButton.Content>
             </ToggleButton>
         </ControlTemplate>
     </RadioButton.Template>
</RadioButton>