Xamarin.Forms has a built-in
ListView
control which offers rich cross-platform functionality including item selection. In case of UWP the color of the selected item is by default determined by the current accent color of the OS. However, it is a common requirement to customize this to better match the branding of your application. In this article we will show how to do so.
Digging into the default style
When it comes to the styling of UWP control, the first place to visit are the default styles of the controls. You can either find a slightly outdated version on-line in the documentation, or you can find them locally on your hard drive as part of the UWP SDKs. Go to file explorer and navigate to the following path:C:\Program Files (x86)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAPIn this folder you are going to find several subfolders for each of the installed versions of UWP. Select the one which your project is targeting, navigate to the
Generic
subfolder and finally open the file generic.xaml
in your favorite text editor. In this rather huge file search for TargetType="ListViewItem"
which should hopefully yield the default style for ListViewItem
control that provides the behavior for each individual item in your ListView
.
Within this style you are going to find out that it uses a number of brush-based resources for different states of the item, including the SelectedBackground
property. This is set as follows:
SelectedBackground="{ThemeResource ListViewItemBackgroundSelected}"Where does this
ListViewItemBackgroundSelected
resource come from? That’s where the second file in the Generic
folder comes into play – themeresources.xaml
. Open it and search for this key to find:
<StaticResource x:Key="ListViewItemBackgroundSelected" ResourceKey="SystemControlHighlightListAccentLowBrush" />So yet another reference! Search again to finally find:
<SolidColorBrush x:Key="SystemControlHighlightListAccentLowBrush" Color="{ThemeResource SystemAccentColor}" Opacity="0.6" />So basically, the selected item is indeed displayed with the system accent color with opacity 0.6. How can we now override this behavior in Xamarin.Forms?
Overriding default color
Application-wide resource
The easier but far less ideal option you have is to override the resource in an application-wide manner. If we provide a customSystemControlHighlightListAccentLowBrush
it will override or instances where this Brush
is used (even including other controls).
To do this, we will go to the UWP project’s App.xaml
file and will add a resource in the Application
‘s resource dictionary:
<Application ...> <Application.Resources> <SolidColorBrush Color="DodgerBlue" x:Key="SystemControlHighlightListAccentLowBrush" /> </Application.Resources> </Application>Because the brush has the same key as the system provided one and it is higher in the hierarchy, it will override the system default. All
ListViews
and other controls in your app should now use the vivid DodgerBlue
color for selected item background.
Custom renderer
The less invasive option is to create a custom version ofListView
with custom renderer on UWP. First we will create a new SelectionColorListView
class in the shared or .NET Standard project:
public class SelectionColorListView : ListView { public static readonly BindableProperty SelectionColorProperty = BindableProperty.Create(nameof(SelectionColor), typeof(Color), typeof(SelectionColorListView), Color.LawnGreen); public Color SelectionColor { get => (Color) GetValue(SelectionColorProperty); set => SetValue(SelectionColorProperty, value); } }Now we need a custom renderer for UWP which will check the custom resource when the control is first set:
[assembly: ExportRenderer(typeof(SelectionColorListView), typeof(SelectionColorListViewRenderer))] namespace XFUwpListViewColors.UWP { public class SelectionColorListViewRenderer : ListViewRenderer { protected override void OnElementChanged(ElementChangedEventArgs<ListView> e) { base.OnElementChanged(e); if (e.NewElement != null) { UpdateSelectionColor(); } } protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) { base.OnElementPropertyChanged(sender, e); if (e.PropertyName == nameof(SelectionColorListView.SelectionColor)) { UpdateSelectionColor(); } } private void UpdateSelectionColor() { if (Control != null && Element is SelectionColorListView listView) { var nativeColor = XamarinColorToNative(listView.SelectionColor); Control.Resources["SystemControlHighlightListAccentLowBrush"] = new SolidColorBrush(nativeColor); } } private Windows.UI.Color XamarinColorToNative(Xamarin.Forms.Color color) { var alpha = (byte)(color.A * 255); var red = (byte)(color.R * 255); var green = (byte)(color.G * 255); var blue = (byte)(color.B * 255); return Windows.UI.Color.FromArgb(alpha, red, green, blue); } } }We are waiting for the element or
SelectionColor
property to be updated and then set the SystemControlHighlightListAccentLowBrush
resource for the underlying control.
Now, you can use your custom ListView
in XAML like this:
<local:SelectionColorListView SelectionMode="Single" SelectionColor="LimeGreen" />Where
local:
must be a declared XAML namespace in the ContentPage
element:
xmlns:local="clr-namespace:NamespaceOfYourCustomListView"Note that updating the color at runtime is not possible, because once the selection is first done, the control will keep using the resource that was resolved for the first time.
Further improvements
To unify the style across platforms, you could now provide custom renderers forListView
controls on Android and iOS as well. This is not required though and Xamarin.Forms will otherwise happily use the default ListViewRenderer
and ignore the SelectionColor
property.
In addition, you may want to customize other ListViewItem
colors as well – the hover background color, pressed background color, etc.. To do this, you can follow the exact same process as outlined above.
Future
At Build 2018 Microsoft announced an upcoming tool that will auto-generate appropariate default style resources for your application based on your branding. This will make our lives significantly easier and unifying the style for the whole application will be as easy as 1,2,3.Source code
Source code for this article is available on my GitHub.
1 thought on “Xamarin.Forms – Changing selected item color in UWP”