How to automatically select all text on focus in Entry,Editor,Label? Use Cross Platforms.
Quantity.IsFocused = true;
No work :(
How to automatically select all text on focus in Entry,Editor,Label? Use Cross Platforms.
Quantity.IsFocused = true;
No work :(
In MainActivity add
public class MyEntryRenderer : EntryRenderer
{
public MyEntryRenderer(Context ctx) : base(ctx) {}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
var nativeEditText = (EditText)Control;
nativeEditText.SetSelectAllOnFocus(true);
}
}
}
and to the top add :
[assembly: ExportRenderer (typeof (Entry), typeof (MyEntryRenderer))]
SetNativeControl(Control)
is redundant; it is essentially saying Control = Control;
. Just do if (Control != null) Control.SetSelectAllOnFocus(true);
Or in c# 6 can reduce the if
test to "null check": Simplifies to: Control?.SetSelectAllOnFocus(true);
–
Bos As mentioned in other answers, if you are using Xamarin Forms 4.2+, you can use the CursorPosition and SelectionLength properties. However, you need to make sure you invoke on the Main/UI thread as all direct manipulation of UI elements must be done there. The app will very likely crash when deployed to a device without doing so, even if it appears to run fine in a simulator.
XAML
<Entry x:Name="MyEntry" Focused="MyEntry_Focused" />
C#
private void MyEntry_Focused(object sender, FocusEventArgs e)
{
Dispatcher.BeginInvokeOnMainThread(() =>
{
MyEntry.CursorPosition = 0;
MyEntry.SelectionLength = MyEntry.Text != null ? MyEntry.Text.Length : 0
});
}
For Xamarin.Forms, you can also use Device.BeginInvokeOnMainThread() rather than Dispatcher. If you're using Xamarin Essentials, there is also MainThread.BeginInvokeOnMainThread() (which does the same as Device.BeginInvokeOnMainThread()).
Xamarin.Forms has a method called Device.BeginInvokeOnMainThread(Action) that does the same thing as MainThread.BeginInvokeOnMainThread(Action). While you can use either method in a Xamarin.Forms app, consider whether or not the calling code has any other need for a dependency on Xamarin.Forms. If not, MainThread.BeginInvokeOnMainThread(Action) is likely a better option.
MyEntry.Text
could be null if user taps on it very early after it has rendered. Make sure to handle that to prevent crash. –
Bellda BeginInvoke..
queues it to happen as soon as it can (but lets current method return first). I recently observed this on a method that tried to change selected text when an entry gains focus. –
Bos 1.Add Focused Event.Cs
protected void Txt_Focussed(object sender, FocusEventArgs e)
{
txt.CursorPosition = 0;
txt.SelectionLength = txt.Text.Length;
}
Set focus
protected override void OnAppearing()
{
base.OnAppearing();
txt.Focus();
}
XAML Code
<Entry x:Name="txt" Text="155134343" Focused="Txt_Focussed" />
Dispatcher.BeginInvokeOnMainThread
, otherwise it doesn't work. Another thing to note is that txt.Text
could be null if user taps on it very early after it has rendered. Make sure to handle that to prevent crash. –
Bellda In MainActivity add
public class MyEntryRenderer : EntryRenderer
{
public MyEntryRenderer(Context ctx) : base(ctx) {}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
var nativeEditText = (EditText)Control;
nativeEditText.SetSelectAllOnFocus(true);
}
}
}
and to the top add :
[assembly: ExportRenderer (typeof (Entry), typeof (MyEntryRenderer))]
SetNativeControl(Control)
is redundant; it is essentially saying Control = Control;
. Just do if (Control != null) Control.SetSelectAllOnFocus(true);
Or in c# 6 can reduce the if
test to "null check": Simplifies to: Control?.SetSelectAllOnFocus(true);
–
Bos @kiddailey posted a nice solution, here is a reusable solution based on that:
Create behavior in code behind
public class SelectContentWhenFocusedBehavior : Behavior<Entry>
{
protected override void OnAttachedTo(Entry entry)
{
entry.Focused += OnFocused;
base.OnAttachedTo(entry);
}
protected override void OnDetachingFrom(Entry entry)
{
entry.Focused -= OnFocused;
base.OnDetachingFrom(entry);
}
private static void OnFocused(object sender, FocusEventArgs args)
{
Device.BeginInvokeOnMainThread(() =>
{
Entry myEntry = sender as Entry;
myEntry.CursorPosition = 0;
myEntry.SelectionLength = myEntry.Text != null ? myEntry.Text.Length : 0;
});
}
}
in your view add the link to the behavior namespace
xmlns:behav="clr-namespace:MyApp.Resources.Behaviors"
Add behavior to your Entry in the view
<Entry Text="{Binding something, Mode=TwoWay}" Keyboard="Numeric">
<Entry.Behaviors>
<behav:SelectContentWhenFocusedBehavior/>
</Entry.Behaviors>
</Entry>
In my case, to make work @SAIJAN KP answer, i made the Focused
handler async
and awaited a small delay to wait the cursor to appear on Entry
:
private async void Entry_Focused(object sender, FocusEventArgs e)
{
await Task.Delay(100);
entryTest.CursorPosition = x;
entryTest.SelectionLength = y;
}
XAML
<Entry x:Name="entryTest" Text="155134343" Focused="Entry_Focused" />
Dispatcher.BeginInvokeOnMainThread
, as seen in kiddaily's later answer. (Deferring until internal entry-focus code completes.) Bottom line: ONLY rely on a delay, if you can't find a "clean" way to ensure internal code is ready to accept your changes. REASON: Required delay might be different on different devices; it is impossible to guarantee that a delay-based solution will work for all devices. –
Bos BeginInvokeOnMainThread
won't solve the problem. DETAILS: I've tested the problem case shown in question, and used kiddailey's answer, and it solves the problem. The reason it works is because it QUEUES an action to main thread. This GUARANTEES that it runs AFTER the CURRENT UI action (xamarin's internal entry-focus logic) completes. This GUARANTEE is safer than an arbitrarily chosen delay. –
Bos The UWP custom entry renderer could be...
using System.ComponentModel;
using Xamarin.Forms;
using Xamarin.Forms.Platform.UWP;
[assembly: ExportRenderer(typeof(Entry), typeof(myApp.UWP.ExtendedEntryRenderer))]
namespace myApp.UWP
{
public class ExtendedEntryRenderer : EntryRenderer
{
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == nameof(Entry.IsFocused)
&& Control != null && Control.FocusState != Windows.UI.Xaml.FocusState.Unfocused)
Control.SelectAll();
}
}
}
I needed to abstract the control's name, so here's what worked for me, and maybe it will help someone else.
In the .xaml page:
<Entry
Text="{Binding QuantityToAdd, Mode=TwoWay}"
Focused="OnEntryFocused">
Other properties not important
private void OnEntryFocused(object sender, FocusEventArgs e)
{
Dispatcher.BeginInvokeOnMainThread(() =>
{
var entry = (Entry)sender;
entry.CursorPosition = 0;
entry.SelectionLength = entry.Text?.Length ?? 0;
});
}
© 2022 - 2025 — McMap. All rights reserved.