Search code examples
xamlgridviewuwpdatatemplateellipse

UWP: how to create a "rounded" color picker


I would like to create a color picker that looks like in Windows Ink: enter image description here

So I've created a GridView that contains my 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>

In the Grid_RightTapped and Grid_Tappent events, I get the clicked color, I colorize my items, and I affect the selected item to the 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;
    }
}

This works well but I would like to know if there is a way to "customize" the template of the selected/hover item of the GridView? These are squares and I would like to replace them by by ellipses, like in Windows Ink.

enter image description here


Solution

  • You need to override ItemContainerStyle for your GridViewItem. Look at the GridViewItemExpanded style in Generic.xaml in C:\Program Files (x86)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\10.0.10240.0\Generic and change Rectangle to Ellipse. And don't forget to setup into your GridView. For example:

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

    Correct Style is:

    <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>
    

    enter image description here