Building An Edit Label Custom Control in Xamarin Forms.

Edit Label Custom Control in Xamarin.Forms XAML
Edit Label Custom Control in Xamarin.Forms XAML

When displaying textual information to your user, you want it to be well displayed with good font size, appropriate style, text color… But you also want the user to edit this information with minimum efforts. Let’s say you have a page in your app with a title, or several labels containing text. And you want the user to edit these as he wish, without switching to a new page. A good scenario will be to tap on the label and edit the test as it focus and display the text as it was, when focus is lost.

This is seen already in several applications. It could be achieved easily in Xamarin Forms by applying custom modifications to Android’s EditText and iOS’ UITextField, then call these as Custom Renderers. But we will achieve this using XAML and only code in the shared project. This blog post is about building this edit label custom control in xamarin forms xaml.

An overview of the control

This control is not complicated and the logic behind it is that. It behaves like a text entry when focused and it behaves like a label when it loses focused. So, to implement it in Xamarin Forms XAML, we will use a contentview, leverage Visual States, Gesture Recognizers and add a few bindable properties to make our control.

Here is the source code for this control

Building our custom control in
Xamarin Forms

First, we create a ContentView which will have the atrribute (x:Name=”thisEdiableLabel”), this attribute will be used for referencing in XAML.

We then add a bunch of bindable properties which will be used to customize our control. The most important property here is the “IsFocusedMode” Property, which we will use to play with the views contained in the ContentView.

public static readonly BindableProperty IsFocusedModeProperty = BindableProperty.Create("IsFocusedMode", typeof(bool), typeof(EditableLabel), default(bool), propertyChanged: OnIsFocusedModePropertyChanged);
        public bool IsFocusedMode
        {
            get { return (bool)GetValue(IsFocusedModeProperty); }
            set { SetValue(IsFocusedModeProperty, value); }
        }

Initially, our control will need to display already available information. So, the content view’s primary content is a label to display this information. This ContentView will switch to edit mode once the Label gets tapped as shown below.

<Label x:Name="MainLabel" FontAttributes="{Binding FontAttributes, Source={x:Reference thisEdiableLabel}}" FontFamily="{Binding FontFamily, Source={x:Reference thisEdiableLabel}}"
                           Text="{Binding Text, Source={x:Reference thisEdiableLabel}, Mode=TwoWay}" TextColor="{Binding TextColor, Source={x:Reference thisEdiableLabel}}" FontSize="{Binding FontSize, Source={x:Reference thisEdiableLabel}}">
                        <Label.GestureRecognizers>
                            <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
                        </Label.GestureRecognizers>
                    </Label>

When tapped, the IsFocusedMode property will be set to true and this will activate the ContentView’s trigger to switch from the label to the entry.

To detect when the user has finished editing and leaves the entry, we will use the Focus Visual State of the Entry. When this visual state is set to false, we launch a Trigger on the ContentView.

<DataTrigger TargetType="local:EditableLabel" Binding="{Binding IsFocused, Source={x:Reference MainEntry}}" Value="False">
            <Setter Property="IsFocusedMode" Value="False"/>
        </DataTrigger>

Here is the XAML code for this content view.

<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="EditableLabel.EditableLabel"
             xmlns:local="clr-namespace:EditableLabel"
             x:Name="thisEdiableLabel">
    <ContentView.Triggers>
        <DataTrigger Binding="{Binding IsFocusedMode, Source={x:Reference thisEdiableLabel}}" Value="False" TargetType="ContentView">
            <Setter Property="Content">
                <Setter.Value>
                    <Label x:Name="MainLabel" FontAttributes="{Binding FontAttributes, Source={x:Reference thisEdiableLabel}}" FontFamily="{Binding FontFamily, Source={x:Reference thisEdiableLabel}}"
                           Text="{Binding Text, Source={x:Reference thisEdiableLabel}, Mode=TwoWay}" TextColor="{Binding TextColor, Source={x:Reference thisEdiableLabel}}" FontSize="{Binding FontSize, Source={x:Reference thisEdiableLabel}}">
                        <Label.GestureRecognizers>
                            <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
                        </Label.GestureRecognizers>
                    </Label>
                </Setter.Value>
            </Setter>
        </DataTrigger>
        <DataTrigger Binding="{Binding  IsFocusedMode, Source={x:Reference thisEdiableLabel}}" Value="True" TargetType="local:EditableLabel">
            <Setter Property="Content">
                <Setter.Value>
                    <Entry Placeholder="{Binding PlaceHolder, Source={x:Reference thisEdiableLabel}}" FontAttributes="{Binding FontAttributes, Source={x:Reference thisEdiableLabel}}" x:Name="MainEntry" 
                           TextColor="{Binding TextColor, Source={x:Reference thisEdiableLabel}}"
                           Text="{Binding Text, Source={x:Reference thisEdiableLabel}, Mode=TwoWay}" FontSize="{Binding FontSize, Source={x:Reference thisEdiableLabel}}"/>
                </Setter.Value>
            </Setter>
            <Setter Property="ContentChanged" Value="True" />
        </DataTrigger>
        <DataTrigger TargetType="local:EditableLabel" Binding="{Binding IsFocused, Source={x:Reference MainEntry}}" Value="False">
            <Setter Property="IsFocusedMode" Value="False"/>
        </DataTrigger>
    </ContentView.Triggers>
</ContentView>

Let’s add finishing touches. At this stage, the Entry when focused, does not always display the keyboard. The cursor is at the beginning of the text too. These can be corrected by setting a few properties when the FocusMode bindable property changes. In our case, the name of the method in charge of this is called : “OnIsFocusedModePropertyChanged”. This is done as shown below.

(bindable as EditableLabel).MainEntry.Focus();
                        (bindable as EditableLabel).MainEntry.CursorPosition = (bindable as EditableLabel).MainEntry.Text?.Length ?? 0;

Demo

Edit Label Custom Control In Xamarin.Forms demo
Edit Label Custom Control In Xamarin.Forms demo
We’re studying how software can help you increase your productivity. Please could you answer these few and interesting questions to help improve this study ? Thankyou. English Questionnaire Or French Questionnaire.Follow me on social media and stay updated

Conclusion

Building custom controls entirely with XAML and C# in the shared project only is easy and fast. Though it might not always be the best when it comes to performance. Here is a similar blog post about building a
SnackBar in Xamarin Forms with XAML. With this, we built our Entire edit label custom control in Xamarin Forms XAML. This required a bit of code behind to mage states and properties. As I said earlier, this could be achieved using custom renderers, but this approach allow’s saves us per platform modification of the control, though it might not be the best when it comes to performance.

References

https://docs.microsoft.com/fr-fr/xamarin/xamarin-forms/app-fundamentals/gestures/tap
https://docs.microsoft.com/fr-fr/xamarin/xamarin-forms/app-fundamentals/triggers
https://docs.microsoft.com/fr-fr/dotnet/api/xamarin.forms.visualelement.isfocused?view=xamarin-forms

If you liked this post, or it was useful to you, please 👍 like it, share it on twitter, facebook or other social media… in case you want to get updated on any new useful post, follow me on twitter,  Github  and like my page on facebook. And every other social media by clicking on the  buttons at the end of this post.Follow me on social media and stay updated

Follow me on social media and stay updated