Ted Nyberg
Ted Nyberg

Reputation: 7391

Set focus to Entry control to trigger keyboard in .NET MAUI app

I'm trying to set focus to an Entry control when a page loads to automatically trigger the keyboard.

However, while the Entry control receives focus (caret blinking), if done during Loaded event, the keyboard doesn't appear.

If done only in the Appearing event, the caret doesn't even appear.

My page has a single Entry like:

<StackLayout>
    <Entry x:Name="RoundsEntry" Keyboard="Numeric" />
</StackLayout>

In the code-behind, I'm setting focus during the Loaded event:

public RoundsPage()
{
    InitializeComponent();

    Loaded += RoundsPage_Loaded;

    // For Shell navigation, the Appearing event makes more sense, 
    // as page is only loaded once, but we want the Entry control 
    // to receive focus every time the user returns to the page.
    Appearing += RoundsPage_Loaded;
}

private void RoundsPage_Loaded(object? sender, EventArgs e)
{
    RoundsEntry.Focus();
}

Manually tapping the Entry control (even though it already has focus) does trigger the keyboard.

Am I missing something, or is there some other option to programmatically trigger (and later hide) the keyboard?

(Tested on Android.)

Edit: seems related to this issue on GitHub, so I think I'm looking for a viable workaround until it's fixed.

Upvotes: 13

Views: 12845

Answers (4)

Mohamed Noordin
Mohamed Noordin

Reputation: 166

It is not a Visual Studio, XAML or .NET MAUI bug at all. It is an architectural concept in the way which .NET MAUI loads views and triggers events. Somehow, the the parent view Loaded event only gets triggered when the view itself loads and not its children views. Suppose we have a content page as following:

<ContentPage ...
    Loaded="OnPageLoaded">

    <StackLayout>
        <Entry x:Name="RoundsEntry" Keyboard="Numeric" />
    </StackLayout>
    </ContentPage>

Code-behind:

private void OnPageLoaded(object? sender, EventArgs e)
{
    System.Diagnostics.Debug.WriteLine("Page loaded");
    RoundsEntry.Focus();
}

If you open the output window in Visual Studio, you will see the above log in there, but you will not have the keyboard triggered up. Why? Basically, because the entry view itself has not been fully loaded; as we said before, the Loaded event gets fired when the view itself gets loaded and nothing else.
Now, if we intend to perform an action for a specific view like setting or unsetting focus, we have to listen for Loaded event on that particular view.

<ContentPage ...>

    <StackLayout>
        <Entry x:Name="RoundsEntry" Keyboard="Numeric"
        Loaded="RoundsEntrySetFocus"/>
    </StackLayout>
    </ContentPage>

Code-behind:

private void RoundsEntrySetFocus(object? sender, EventArgs e)
{
    System.Diagnostics.Debug.WriteLine("RoundsEntry loaded");
    RoundsEntry.Focus();
}

If you run the app, you will see the above log in the output window, and the keyboard will get triggered up. The same concept applies for the Editor and all other views. This behavior is consistent across various mobile platforms, including Android and iOS.

Upvotes: 3

Arvind Chourasiya
Arvind Chourasiya

Reputation: 17422

This is how I did on OnAppearing of xaml.cs file

protected override void OnAppearing()
{
   base.OnAppearing();
   txtName.Loaded += delegate { txtName.Focus(); };
}

txtName is Name of Entry control.

Upvotes: 1

Dennis de Wilde
Dennis de Wilde

Reputation: 41

This was bugging me for a while now.

It seems the Loaded event is too soon to be setting focus. i couldn't find another event after 'loaded' so the dirty work around that worked for me is building in a slight delay.

public partial class MainPage: ContentPage {
  public MainPage() {
    InitializeComponent();
    Loaded += MainPage_Loaded;
  }

  private void MainPage_Loaded(object sender, EventArgs e) {
    _ = Task.Delay(200).ContinueWith(t =>{
      entry.Focus();
    });
  }
}

Upvotes: 4

Jianwei Sun - MSFT
Jianwei Sun - MSFT

Reputation: 4302

I think it's a question or a bug of which piece of version. Such as Visual Studio, .NET ...

Here is the code:

public partial class MainPage : ContentPage
{
    
    public MainPage()
    {
        InitializeComponent();
        Loaded += MainPage_Loaded;
    }

   private void MainPage_Loaded(object sender, EventArgs e)
    {
        entry.Focus();
    }
}
<VerticalStackLayout>        
    <Entry x:Name="entry" Keyboard="Numeric"/>    
</VerticalStackLayout>

VS: Community 2022 (64-bit) 17.3.4 --- .NET:6.0 --- Android: API 32

This is my screen recording

Upvotes: 9

Related Questions