D.L.
D.L.

Reputation: 211

Why is Unfocused event triggered while typing on an Entry?

In my Xamarin Forms application I would like to perform a validation on an Entry element when the user focus it out. Using Completed event only works when the user taps "enter" on the keyboard. I tried to use Unfocused but this event triggers while the user is typing on the Entry element and I really do not understand why.

How could I perform a piece of code only when an Entry element is unfocused?

I've 10 ViewCell elements like this one:

<ViewCell >
                        <StackLayout Orientation="Horizontal" Padding="13, 5" >
                            <StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand" Spacing="1">
                                <Label Text="Matricola" VerticalOptions="Center" HorizontalOptions="StartAndExpand" ></Label>
                                <Entry x:Name="matricola" Text="{Binding Paziente.MatricolaPaziente, Mode=TwoWay}" HorizontalOptions="FillAndExpand" Completed="Entry_Completed" Unfocused="Entry_Completed" ></Entry>
                                <Label Text="{Binding RegistrationValidator.MatricolaError, Mode=OneWay}" HorizontalOptions="FillAndExpand" TextColor="IndianRed"></Label>
                            </StackLayout>
                        </StackLayout>
                    </ViewCell>

Code behind:

private async void Entry_Completed(object sender, EventArgs e){
// Some code here
}

Moreover the event triggers with unexpected random senders (other Entry elements, always with e.IsFocused == false)

Upvotes: 2

Views: 4264

Answers (4)

Ben
Ben

Reputation: 2995

The Entry focus issue inside ListView seems to occur (on second row of the ListView and onwards) on Android (8.1 and 9.0) (Xamarin.Forms 4.5.0.356).

See also "Entry focus issue inside ListView".

As a workaround, use CollectionView (without ViewCell in ItemTemplate).

Sample without Entry focus issue:

<CollectionView>
  <CollectionView.ItemsSource>
    <x:Array Type="{x:Type x:String}">
      <x:String>First</x:String>
      <x:String>Second</x:String>
    </x:Array>
  </CollectionView.ItemsSource>
  <CollectionView.ItemTemplate>
    <DataTemplate>
      <Entry Text="collectionview" Focused="Entry_Unfocused" Unfocused="Entry_Unfocused" />
    </DataTemplate>
  </CollectionView.ItemTemplate>
</CollectionView>

Sample with Entry focus issue in ListView on Android (8.1 and 9.0):

<ListView>
  <ListView.ItemsSource>
    <x:Array Type="{x:Type x:String}">
      <x:String>First</x:String>
      <x:String>Second</x:String>
    </x:Array>
  </ListView.ItemsSource>
  <ListView.ItemTemplate>
    <DataTemplate>
      <ViewCell>
        <Entry Text="listview" Focused="Entry_Unfocused" Unfocused="Entry_Unfocused" />
      </ViewCell>
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>

Codebehind for observing the focus events:

void Entry_Unfocused(object sender, FocusEventArgs e)
{
    Debug.WriteLine($"Entry_Unfocused:{e.IsFocused}:");
}

void Entry_Focused(object sender, FocusEventArgs e)
{
    Debug.WriteLine($"Entry_Focused:{e.IsFocused}:");
}

Upvotes: 3

Wendy Zang - MSFT
Wendy Zang - MSFT

Reputation: 10978

Unfocused event is raised whenever the Entry loses focus. I make a simple code to test and verify.

Xaml:

 <ListView ItemsSource="{Binding list}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Entry Text="{Binding Name}" Unfocused="Entry_Unfocused" />
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

Code:

public partial class EntryPage : ContentPage
{
    public ObservableCollection<Person> list { get; set; }
    public EntryPage()
    {
        InitializeComponent();
        list = new ObservableCollection<Person>()
        {
            new Person (){ Name="A"},
            new Person (){ Name="B"}
        };

        this.BindingContext = this;
    }

    private void Entry_Unfocused(object sender, FocusEventArgs e)
    {

    }
}
public class Person
{
    public string Name { get; set; }
}

enter image description here

Upvotes: 0

Marcel Callo
Marcel Callo

Reputation: 437

I tried with a sample forms like this

 <ContentPage.Content>
    <StackLayout Spacing="20" Padding="15">
        <Label Text="Text" FontSize="Medium" />
        <Entry Text="{Binding Item.Text}" d:Text="Item name" FontSize="Small" Unfocused="Entry_Unfocused" Completed="Entry_Completed" />
        <Label Text="Description" FontSize="Medium" />
        <Editor Text="{Binding Item.Description}" d:Text="Item description" FontSize="Small" Margin="0" />
    </StackLayout>
</ContentPage.Content>

And in the code behind:

 private void Entry_Unfocused(object sender, FocusEventArgs e)
    {
        var txt = ((Entry)sender).Text;

        DisplayAlert("Info", $"Value of text after entry lost focus : {txt} ", "OK");
    }

    private void Entry_Completed(object sender, EventArgs e)
    {
        var txt = ((Entry)sender).Text; 

        DisplayAlert("Info", $"Value when Enter Key is tapped : {txt} ", "OK");
    }

Everything works fine! While looking into your code again, it seems your are in listview. Maybe the problem might come from there.

Upvotes: 1

Jonathan Cook
Jonathan Cook

Reputation: 63

I believe the Unfocused event gets triggered regardless of focus or unfocus, but the FocusEventArgs on the event should have a bool called IsFocused which should show whether or not the Entry is still focused. Have you tried checking that? It looks like you Unfocused Event Handler just uses a generic EventArgs when it could be using the more specific FocusEventArgs

Upvotes: 0

Related Questions