Universal Windows Platform – Custom ComboBox

Custom Combobox demonstrates how to create a custom Style for a ComboBox Control

Step 1

If not already, follow Setup and Start on how to Install and get Started with Visual Studio 2017 or in Windows 10 choose Start, and then from the Start Menu find and select Visual Studio 2017.

vs2017

Step 2

Once Visual Studio Community 2017 has started, from the Menu choose File, then New then Project…

vs2017-file-new-project

Step 3

From New Project choose Visual C# from Installed, Templates then choose Blank App (Universal Windows) and then type in a Name and select a Location and then select Ok to create the Project
vs2017-new-project-window

Step 4

Then in New Universal Windows Project you need to select the Target Version this should be at least the Windows 10, version 1803 (10.0; Build 17134) which is the April 2018 Update and the Minimum Version to be the same.

vs2017-target-platform

The Target Version will control what features your application can use in Windows 10 so by picking the most recent version you’ll be able to take advantage of those features. To make sure you always have the most recent version, in Visual Studio 2017 select Tools Extensions and Updates… then and then see if there are any Updates

Step 5

Once the Project is created from the Solution Explorer select App.xaml

vs2017-app

Step 6

From the Menu choose View and then Designer

vs2017-view-designer

Step 7

Once in the Design View for App.xaml between the Application and /Application elements the following should be entered:

<Application.Resources>
	<Style x:Key="CustomComboBox" TargetType="ComboBox">
		<Setter Property="Padding" Value="12,5,0,7"/>
		<Setter Property="MinWidth" Value="{ThemeResource ComboBoxThemeMinWidth}"/>
		<Setter Property="Foreground" Value="Gold"/>
		<Setter Property="Background" Value="{ThemeResource ComboBoxBackground}"/>
		<Setter Property="BorderBrush" Value="{ThemeResource ComboBoxBorderBrush}"/>
		<Setter Property="BorderThickness" Value="{ThemeResource ComboBoxBorderThemeThickness}"/>
		<Setter Property="TabNavigation" Value="Once"/>
		<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
		<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
		<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled"/>
		<Setter Property="ScrollViewer.VerticalScrollMode" Value="Auto"/>
		<Setter Property="ScrollViewer.IsVerticalRailEnabled" Value="True"/>
		<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False"/>
		<Setter Property="ScrollViewer.BringIntoViewOnFocusChange" Value="True"/>
		<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
		<Setter Property="HorizontalAlignment" Value="Left"/>
		<Setter Property="VerticalAlignment" Value="Top"/>
		<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
		<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
		<Setter Property="ItemsPanel">
			<Setter.Value>
				<ItemsPanelTemplate>
					<CarouselPanel/>
				</ItemsPanelTemplate>
			</Setter.Value>
		</Setter>
		<Setter Property="Template">
			<Setter.Value>
				<ControlTemplate TargetType="ComboBox">
					<Grid x:Name="LayoutRoot">
						<Grid.Resources>
							<Storyboard x:Key="OverlayOpeningAnimation">
								<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity">
									<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0.0"/>
									<SplineDoubleKeyFrame KeySpline="0.1,0.9 0.2,1.0" KeyTime="0:0:0.383" Value="1.0"/>
								</DoubleAnimationUsingKeyFrames>
							</Storyboard>
							<Storyboard x:Key="OverlayClosingAnimation">
								<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity">
									<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="1.0"/>
									<SplineDoubleKeyFrame KeySpline="0.1,0.9 0.2,1.0" KeyTime="0:0:0.216" Value="0.0"/>
								</DoubleAnimationUsingKeyFrames>
							</Storyboard>
						</Grid.Resources>
						<Grid.ColumnDefinitions>
							<ColumnDefinition Width="*"/>
							<ColumnDefinition Width="32"/>
						</Grid.ColumnDefinitions>
						<Grid.RowDefinitions>
							<RowDefinition Height="Auto"/>
							<RowDefinition Height="*"/>
						</Grid.RowDefinitions>
						<VisualStateManager.VisualStateGroups>
							<VisualStateGroup x:Name="CommonStates">
								<VisualState x:Name="Normal"/>
								<VisualState x:Name="PointerOver">
									<Storyboard>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="Background">
											<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxBackgroundPointerOver}"/>
										</ObjectAnimationUsingKeyFrames>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="Background">
											<DiscreteObjectKeyFrame KeyTime="0" Value="GoldenRod"/>
										</ObjectAnimationUsingKeyFrames>
									</Storyboard>
								</VisualState>
								<VisualState x:Name="Pressed">
									<Storyboard>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="Background">
											<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxBackgroundPressed}"/>
										</ObjectAnimationUsingKeyFrames>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="Background">
											<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxBorderBrushPressed}"/>
										</ObjectAnimationUsingKeyFrames>
									</Storyboard>
								</VisualState>
								<VisualState x:Name="Disabled">
									<Storyboard>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="Background">
											<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxBackgroundDisabled}"/>
										</ObjectAnimationUsingKeyFrames>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="Background">
											<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxBorderBrushDisabled}"/>
										</ObjectAnimationUsingKeyFrames>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="HeaderContentPresenter">
											<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxForegroundDisabled}"/>
										</ObjectAnimationUsingKeyFrames>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
											<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxForegroundDisabled}"/>
										</ObjectAnimationUsingKeyFrames>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="PlaceholderTextBlock">
											<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxForegroundDisabled}"/>
										</ObjectAnimationUsingKeyFrames>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="DropDownGlyph">
											<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxDropDownGlyphForegroundDisabled}"/>
										</ObjectAnimationUsingKeyFrames>
									</Storyboard>
								</VisualState>
							</VisualStateGroup>
							<VisualStateGroup x:Name="FocusStates">
								<VisualState x:Name="Focused">
									<Storyboard>
										<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="HighlightBackground"/>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="HighlightBackground">
											<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxBackgroundBorderBrushFocused}"/>
										</ObjectAnimationUsingKeyFrames>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
											<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxForegroundFocused}"/>
										</ObjectAnimationUsingKeyFrames>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="PlaceholderTextBlock">
											<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxForegroundFocused}"/>
										</ObjectAnimationUsingKeyFrames>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="DropDownGlyph">
											<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxDropDownGlyphForegroundFocused}"/>
										</ObjectAnimationUsingKeyFrames>
									</Storyboard>
								</VisualState>
								<VisualState x:Name="FocusedPressed">
									<Storyboard>
										<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="HighlightBackground"/>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
											<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxForegroundFocusedPressed}"/>
										</ObjectAnimationUsingKeyFrames>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="PlaceholderTextBlock">
											<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxPlaceHolderForegroundFocusedPressed}"/>
										</ObjectAnimationUsingKeyFrames>
										<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="DropDownGlyph">
											<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxDropDownGlyphForegroundFocusedPressed}"/>
										</ObjectAnimationUsingKeyFrames>
									</Storyboard>
								</VisualState>
								<VisualState x:Name="Unfocused"/>
								<VisualState x:Name="PointerFocused"/>
								<VisualState x:Name="FocusedDropDown">
									<Storyboard>
										<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="PopupBorder">
											<DiscreteObjectKeyFrame KeyTime="0">
												<DiscreteObjectKeyFrame.Value>
													<Visibility>Visible</Visibility>
												</DiscreteObjectKeyFrame.Value>
											</DiscreteObjectKeyFrame>
										</ObjectAnimationUsingKeyFrames>
									</Storyboard>
								</VisualState>
							</VisualStateGroup>
							<VisualStateGroup x:Name="DropDownStates">
								<VisualState x:Name="Opened">
									<Storyboard>
										<SplitOpenThemeAnimation ClosedTargetName="ContentPresenter"
										OffsetFromCenter="{Binding TemplateSettings.DropDownOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}"
										OpenedTargetName="PopupBorder" OpenedLength="{Binding TemplateSettings.DropDownOpenedHeight, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
									</Storyboard>
								</VisualState>
								<VisualState x:Name="Closed">
									<Storyboard>
										<SplitCloseThemeAnimation ClosedTargetName="ContentPresenter"
										OffsetFromCenter="{Binding TemplateSettings.DropDownOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}"
										OpenedTargetName="PopupBorder" OpenedLength="{Binding TemplateSettings.DropDownOpenedHeight, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
									</Storyboard>
								</VisualState>
							</VisualStateGroup>
						</VisualStateManager.VisualStateGroups>
						<Border x:Name="Background" BorderBrush="Salmon" BorderThickness="{TemplateBinding BorderThickness}"
						Background="LightSalmon" Grid.ColumnSpan="2" Grid.Row="1" CornerRadius="15"/>
						<Border x:Name="HighlightBackground" BorderBrush="Gold" BorderThickness="{TemplateBinding BorderThickness}"
						Background="{ThemeResource ComboBoxBackgroundUnfocused}" Grid.ColumnSpan="2" Opacity="0" Grid.Row="1" CornerRadius="15"/>
						<ContentPresenter x:Name="ContentPresenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
						Margin="{TemplateBinding Padding}" Grid.Row="1" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" CornerRadius="15">
							<TextBlock x:Name="PlaceholderTextBlock" Foreground="{ThemeResource ComboBoxPlaceHolderForeground}"
							Text="{TemplateBinding PlaceholderText}"/>
						</ContentPresenter>
						<FontIcon x:Name="DropDownGlyph" AutomationProperties.AccessibilityView="Raw" Grid.Column="1" Foreground="Gold"
						FontSize="12" FontFamily="{ThemeResource SymbolThemeFontFamily}" Glyph="" HorizontalAlignment="Right"
						IsHitTestVisible="False" Margin="0,10,10,10" Grid.Row="1" VerticalAlignment="Center"/>
						<Popup x:Name="Popup">
							<Border x:Name="PopupBorder" BorderBrush="Salmon"
							BorderThickness="{ThemeResource ComboBoxDropdownBorderThickness}"
							Background="LightSalmon" HorizontalAlignment="Stretch"
							Margin="0,-1,0,-1" CornerRadius="15">
								<ScrollViewer x:Name="ScrollViewer" AutomationProperties.AccessibilityView="Raw"
									BringIntoViewOnFocusChange="{TemplateBinding ScrollViewer.BringIntoViewOnFocusChange}"
									Foreground="{ThemeResource ComboBoxDropDownForeground}"
									HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
									HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
									IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
									IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
									IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
									MinWidth="{Binding TemplateSettings.DropDownContentMinWidth, RelativeSource={RelativeSource Mode=TemplatedParent}}"
									VerticalSnapPointsType="OptionalSingle" VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
									VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}" VerticalSnapPointsAlignment="Near" ZoomMode="Disabled">
									<ItemsPresenter Margin="{ThemeResource ComboBoxDropdownContentMargin}"/>
								</ScrollViewer>
							</Border>
						</Popup>
					</Grid>
				</ControlTemplate>
			</Setter.Value>
		</Setter>
	</Style>
</Application.Resources>

Within the App.xaml is defined an Application.Resources with a Style of “CustomComboBox” and a TargetType of ComboBox – this example takes a copy of the style for the standard ComboBox and customises many of the properties including Foreground set to “Gold”, during the VisualState of PointerOver a BorderBrush has been set to “GoldenRod”.

The Border has the default BorderBrush set to “Salmon” and the Background to “LightSalmon” with a CornerRadius set to “15” and the HighlightBackground has the BorderBrush set to “Gold” and the CornerRadius set to “15”, the ContentPresenter also has the CornerRadius set to “15”. The Popup has it’s BorderBrush set to “Salmon” and the Background to “LightSalmon” – some other elements including the Header have been removed to simplify the ComboBox.

Step 8

In the Solution Explorer select MainPage.xaml

vs2017-mainpage

Step 9

From the Menu choose View and then Designer

vs2017-view-designer

Step 10

The Design View will be displayed along with the XAML View and in this between the Grid and /Grid elements, enter the following XAML:

<ComboBox SelectedIndex="0" Width="200" HorizontalAlignment="Center" VerticalAlignment="Center" Style="{StaticResource CustomComboBox}">
	<ComboBoxItem Content="ComboBox"/>
	<ComboBoxItem Content="One"/>
	<ComboBoxItem Content="Two"/>
	<ComboBoxItem Content="Three"/>
	<ComboBoxItem Content="Four"/>
</ComboBox>

The block of XAML represents the ComboBox Control with the Style of the the CustomCombobox.

Step 11

That completes the Universal Windows Platform Application so Save the Project then in Visual Studio select the Local Machine to run the Application

vs2017-local-machine

Step 12

After the Application has started running you can then select ComboBox if not already selected and then select one of the items from the ComboBox

ran-custom-combobox

Step 13

To Exit the Application select the Close button in the top right of the Application

vs2017-close

For this example Expression Blend was used to create a copy of the Style for a ComboBox which was then customised with a look-and-feel that’s been used in previous tutorials just to demonstrate how different a standard input control can be modified to look completelt different from the standard, this could be to confirm to a corporate colour scheme or part of a fully customised design, this is just the start of how far you can take customising controls for an application.

Creative Commons License

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s