Reputation: 7391
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
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
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
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
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