Xamarin Editor with Placeholder (Using Data Triggers)

Hello everyone, I am back today with a quick tip for Xamarin Forms. Today I did a cool little trick to add a placeholder label to an Editor in Xamarin Forms. The Entry in Xamarin Forms comes with a neat little placeholder!

Screen Shot 2018-08-07 at 13.18.34.pngScreen Shot 2018-08-07 at 13.18.22.png

The Editor in Xamarin Forms does not have a placeholder property, so today I will show you how to add one! The results of this post can be seen in the gif below!

placeholdereditor.gif

Introduction

Placeholders are to be expected on enterable text fields. Unfortunately for whatever reason the Editor in Xamarin doesn’t have a placeholder property. On iOS there is a UIKit object called a UITextView which I could have sworn had a placeholder property, however on closer inspection I found out that it didn’t. That explains why Xamarin never put it in!

Anyway I want to use an Editor in my code with a placeholder since I require a text entry with multiple lines and scrolling, exactly the functionality that Editor provides. So today I will be showing you how to add a placeholder to an Editor, purely in XAML using no platform specific code! Please note that this feature is actually coming in Xamarin Forms 3.2. As you can see from this issue on GitHub, the work has been completed and will be included with vanilla Xamarin in 3.2. However I am impatient and need this functionality now, plus we are going to use a cool Xamarin feature to implement the placeholder, so it’s worth staying around!

Since this will be technically deprecated in the next release, I won’t turn this into a full control!

Starting

Before we add our placeholder, I will show you the base XAML template I’m working from. I have a frame displayed in the middle of the content page. Inside the frame I have placed a Grid (to display my editor). You don’t need to worry about any of this code from the frame outwards, everything that you need will be done inside the grid!

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             xmlns:local="clr-namespace:PlaceholderEditor" 
             x:Class="PlaceholderEditor.MainPage"
             BackgroundColor="Aqua">


    <Frame WidthRequest="200" 
    HeightRequest="200" 
    VerticalOptions="Center" 
    HorizontalOptions="Center" 
    CornerRadius="20">

        <Grid RowSpacing="0" ColumnSpacing="0" Margin="-20">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="5"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="5"/>
            </Grid.ColumnDefinitions>

            <Grid.RowDefinitions>
                <RowDefinition Height="5"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="5"/>
            </Grid.RowDefinitions>

        </Grid>
    </Frame>

</ContentPage>
Screen Shot 2018-08-07 at 13.27.31.png
This about XAML code provides us with our base

Tangent

I’ll quickly explain the XAML above. I have added a Grid inside of a frame. I have added a negative margin so that the contents of the grid is equal to the padding of the frame. The frame applies a padding to it’s children by default, so I have just overriden this behaviour. Next I have created 3 columns and rows, creating a border of width 5 inside my grid. Any content I add will be put into the centre of the grid (I like having some padding so I can easily edit positioning later.

Adding an Editor

Drop the Following XAML anywhere inside of your grid:

<Editor x:Name="notesTextView" 
        Margin="5,0,5,0" 
        BackgroundColor="Transparent"
        Text="Hello"
        Grid.Row="1" 
        Grid.RowSpan="1" 
        Grid.Column="1" 
        Grid.ColumnSpan="1"/>

Here I have given you the editor, placed nicely into the grid. I have applied a margin to taste (I don’t like where the editor is positioned by default. I have given the Editor a reference (with x:Name), this is important as we need to access it later (don’t worry there will be no codebehind here!). Finally I have set the background colour to be transparent (it is white by default). This is because we will be adding a label behind the Editor and showing and hiding that based on a given condition (no text in the editor).

The editor should look like this:

Screen Shot 2018-08-07 at 13.37.22.png

Adding a Label

Add the following XAML ABOVE your Editor (this places it behind the editor on the grid). I also suggest commenting out your editor so you can style your placeholder to taste.

<Label Text="Tap To Add Text" 
       TextColor="Gray"
       Opacity="0.5" Margin="8,8,8,8"
       Grid.Row="1" 
       Grid.RowSpan="1" 
       Grid.Column="1" 
       Grid.ColumnSpan="1"/>

I added the margin to position the label to the start location of text in the entry. This might be a bit fiddly and certainly is no exact science. Otherwise I just made the placeholder look as close to the default Entry placeholder as I could.

The label should look like this:

Screen Shot 2018-08-07 at 13.40.33.png

Adding a Data Trigger

Now for the fun stuff! We are going to add a data trigger to our label to show/hide it based on whether theEditor has text. You can read about DataTriggers more here, but basically they give us an easy way to add interactions to our view, purely in XAML. This helps make our app more maintainable because there is a greater separation of concerns (from views, data, animations etc).

Go back to your label and update it with the following:

<Label Text="Tap To Add Text" 
       TextColor="Gray"  
       Grid.Row="1" 
       Grid.RowSpan="1" 
       Grid.Column="1" 
       Grid.ColumnSpan="1" 
       Opacity="0.5" 
       Margin="8,8,8,8">
</Label>

We have opened up the Label so that we can add a data trigger to it. Also I have set the label to be hidden by default.

Next add access the Labelsdata triggers:

<Label ...>
    <Label.Triggers>

    </Label.Triggers>
</Label>

And add a DataTrigger inside the Triggers bracket:

<Label ...>
    <Label.Triggers>
        <DataTrigger>

        </DataTrigger>
    </Label.Triggers>
</Label>

Now we need to set our data trigger to observe the Editor Set the following options:

  • TargetType: In this case it is a Label
  • Binding: We need to set this equal to the Text property of the Editor
  • Value: We now need to tell the DataTrigger what values it should listen for.

This would look like the following:

<DataTrigger TargetType="Label"                   
             Binding="{Binding Source={x:Reference notesTextView}, Path=Text.Length}"
             Value="0">
</DataTrigger>

As you can see we have set our binding equal to the Text.Length property of the Editor. Now when the Text.Length property of the Editor equals 0, our data trigger will fire. That’s all well and good, except we haven’t told it to do anything yet!

Inside of the DataTrigger tag, open a new tag, Setter. We can use a Setter to execute some ‘code’ in our XAML! So now lets set the IsVisible property to true:

<Setter Property="IsVisible" Value="true"/>

Now whenever the DataTrigger fires, the Label we are using as our placeholder will be visible for as long as the Editor is empty.

Your completed code should look like this:

<Label IsVisible="false" Text="Tap To Add Text" TextColor="Gray"
                Grid.Row="1" Grid.RowSpan="1" Grid.Column="1" Grid.ColumnSpan="1" Opacity="0.5" Margin="8,8,8,8">
    <Label.Triggers>
        <DataTrigger TargetType="Label"
                        Binding="{Binding Source={x:Reference notesTextView}, Path=Text.Length}"
                        Value="0">
            <Setter Property="IsVisible" Value="true"/>
        </DataTrigger>

        <DataTrigger TargetType="Label">

        </DataTrigger>
    </Label.Triggers>
</Label>

<Editor x:Name="notesTextView" 
        Margin="5,0,5,0" 
        BackgroundColor="Transparent"
        Text="Hello"
        Grid.Row="1" 
        Grid.RowSpan="1" 
        Grid.Column="1" 
        Grid.ColumnSpan="1"/>

Run the app and empty the editor. The placeholder should appear, and then disappear when you start typing!

placeholdereditor.gif

Thats it from me, I hope you enjoyed this quick tip to create a placeholder label using DataTriggers.

You can find the completed solution available on GitHub

You can find me on the following sites:

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 )

Connecting to %s