Is there a way to force entry to uppercase and How can I uppercase the items inside the picker? If possible without using plugins
Is there a way to force entry to uppercase and How can I uppercase the items inside the picker? If possible without using plugins
For the Entry, you can change the text to uppercase in TextChanged event.
For the Picker, you usually control the ItemsSource, you just need to uppercase every string in the ItemsSource.
public MainPage()
{
InitializeComponent();
IList<Item> dummyData= new List<Item>
{
new Item { Id = 0, Name = "Item 0" },
new Item { Id = 1, Name = "Item 1" },
new Item { Id = 2, Name = "Item 2" },
};
picker.ItemsSource = dummyData
.Select(i => i.Name.ToUpperInvariant())
.ToList();
entry.TextChanged += OnTextChanged;
}
private void OnTextChanged(object sender, TextChangedEventArgs e)
{
(sender as Entry).Text = e.NewTextValue.ToUpperInvariant();
}
If you're using MVVM, you can use a custom converter for Entry.Text and Picker.ItemsSource binding to change the value to uppercase.
If you want to force UpperCase in the Entry there are a few ways to do this but let's use Effects this time.
If you haven't heard about Effects you can quickly read what are they for here
First you will need to create the effect in the Xamarin.Forms Project.
For simplicity I will call it EntryAllCapitalEffect and the code looks like this:
namespace YourAwesomeNamespace
{
public class EntryAllCapitalEffect : RoutingEffect
{
public EntryAllCapitalEffect() : base("StackOverflow.EntryAllCapitalEffect")
{
}
}
}
Where StackOverflow is your company name and EntryAllCapitalEffect is the effect name.
Now we need to implement the effect in each one of the Platform Projects.
Let's start with Android:
Let's create a file into the Android Project with the name EntryAllCapitalEffect and add the code below as part of the implementation.
[assembly: ResolutionGroupName("StackOverflow")] //Remember your companyName ?
[assembly: ExportEffect(typeof(YourAwesomeNamespace.Droid.EntryAllCapitalEffect), "EntryAllCapitalEffect")]
namespace YourAwesomeNamespace.Droid
{
public class EntryAllCapitalEffect : PlatformEffect
{
protected override void OnAttached()
{
try
{
//Let's don't do anything if the control is not a EditText
if (!(Control is EditText editText))
{
return;
}
//Force the keyboard setup all Caps letters
// But the user can still change the Caps taping on Shift
editText.InputType = InputTypes.TextFlagCapCharacters;
// Update any lowercase into Uppercase
var filters = new List<IInputFilter>(editText.GetFilters());
filters.Add(new InputFilterAllCaps());
editText.SetFilters(filters.ToArray());
}
catch (Exception) { }
}
protected override void OnDetached()
{
}
}
}
Now let's continue with iOS
Same as of Android, let's create a file into the iOS Project with the name EntryAllCapitalEffect. Add the code below into the class.
[assembly: ResolutionGroupName("StackOverflow")] // Again your CompanyName
[assembly: ExportEffect(typeof(YourAwesomeNamespace.iOS.EntryAllCapitalEffect), "EntryAllCapitalEffect")]
namespace YourAwesomeNamespace.iOS
{
public class EntryAllCapitalEffect : PlatformEffect
{
protected override void OnAttached()
{
try
{
if (!(Control is UITextField uiTextField))
{
return;
}
//Force the keyboard setup all Caps letters
// But the user can still change the Caps taping on Shift
uiTextField.AutocapitalizationType = UITextAutocapitalizationType.AllCharacters;
//Delegate to replace any Lowercase entry into UpperCase
uiTextField.ShouldChangeCharacters = OnShouldChangeCharacters;
}
catch (Exception) { }
}
protected override void OnDetached()
{
}
private bool OnShouldChangeCharacters(UITextField textfield, NSRange range, string replacementString)
{
using (NSString original = new NSString(textfield.Text), newString = new NSString(replacementString.ToUpper()))
{
textfield.Text = original.Replace(range, newString);
}
return false;
}
}
}
Ok so now to use it just assign it to any Entry in the XAML like this:
<Entry HorizontalOptions="FillAndExpand" Placeholder="Enter Text here" >
<Entry.Effects>
<local:EntryAllCapitalEffect />
</Entry.Effects>
</Entry>
Remember to add the local alias in the XAML
xmlns:local="clr-namespace:YourAwesomeNamespace"
This will be the namespace where your Effect is found.
Note: Your CompanyName can be anything but it must match is all placed this is used.
Note 2: If you have other Effects you don't need to repeat the CompanyName Registration. This is done only once by platform.
Hope this helps.-
Here is on more solution based on @Roger Leblanc's answer
Create a behavior:
public class AllCapsBehavior : Behavior<Entry>
{
protected override void OnAttachedTo(Entry entry)
{
entry.TextChanged += OnEntryTextChanged;
base.OnAttachedTo(entry);
}
protected override void OnDetachingFrom(Entry entry)
{
entry.TextChanged -= OnEntryTextChanged;
base.OnDetachingFrom(entry);
}
private static void OnEntryTextChanged(object sender, TextChangedEventArgs args)
{
((Entry)sender).Text = args.NewTextValue.ToUpperInvariant();
}
}
Add namespace reference to view:
xmlns:behav="clr-namespace:yourproject.Resources.Behaviors"
Add behavior to Entry:
<Entry>
<Entry.Behaviors>
<behav:AllCapsBehavior/>
</Entry.Behaviors>
</Entry>