Uppercase letter in a SearchBar - Xamarin Forms

1

I need to have the uppercase letter in a SearchBar, the code that I was able to do that seemed closer to reality is this one below, but it did not work:

//Pesquisa localmente a cada letra digitada
private void OnTextChanged(object sender, TextChangedEventArgs e)
{
    //Letra Maiúscula
    MainSearchBar.Text.ToUpper();
}

Declaration of SearchBar :

<!-- Pesquisa -->
<SearchBar x:Name="MainSearchBar" 
           Placeholder="Digite o nome do produto..." 
           Margin="10, 12, 10, 0" 
           BackgroundColor="LightGray" 
           TextChanged="OnTextChanged"/>
    
asked by anonymous 14.05.2018 / 22:46

2 answers

0

I got help from a colleague who is very simple and worked perfectly:

MainSearchBar.Text = MainSearchBar.Text.ToUpper();
    
15.05.2018 / 22:18
1

The event itself does not provide the ability to change user input, as it is triggered after the text has already been changed.

This is far from the ideal solution, I particularly would not recommend, inclusive. But to make your code work it would look like this:

private void OnTextChanged(object sender, TextChangedEventArgs e)
{
    if(!string.IsNullOrWhiteSpace(e.NewTextValue))
        ((SearchBar)sender).Text = e.NewTextValue.ToUpper();
}

Alternatives

Use a component that handles data entry

GitHub has the 'CapitalizeKeyboard' component, for example . It provides the ability to force entry into uppercase.

See an example of it working on android and iOS:

MVVM - Using ValueConverter

You would use this Converter :

public class CapitalizeTextConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return Capitalize(value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return Capitalize(value);
    }

    private object Capitalize(object value)
    {
        if (value == null || !(value is string) || string.IsNullOrWhiteSpace(value)) 
            return value;

        return value.ToString().ToUpper();
    }
}

In this case, your statement in XAML would look like this:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:converter="clr-namespace:App.Converters"
             xmlns:viewModel="clr-namespace:App.ViewModels"
             x:Class="App.Views.SettingsPage">
    <ContentPage.Resources>
        <ResourceDictionary>
            <converter:CapitalizeTextConverter x:Key="CapitalizeTextConverter" />
        </ResourceDictionary>
    </ContentPage.Resources>
    <ContentPage.BindingContext>
        <viewModel:MyViewModel/>
    </ContentPage.BindingContext>
    <StackLayout>
        ... 
        <SearchBar Text="{Binding SearchText, Converter={StaticResource CapitalizeTextConverter}}"
                   SearchCommand="{Binding SearchCommand}"/>
        ... 
    </StackLayout>
</ContentPage>

You would need the ViewModel to handle the data itself. You could declare it like this:

public class MyViewModel : INotifyPropertyChanged
{
    private string searchText;
    public string SearchText
    {
        get{ return searchText; }
        set
        {
            if(value != searchText)
            {
                searchText = value;
                OnPropertyChanged("SearchText");
            }
        }
    }

    public Command SearchCommand { get; set; }

    public MyViewModel()
    {
        SearchCommand = new Command(ExecuteSearch);
    }

    private void ExecuteSearch()
    {
        // Aqui você faria a lógica da busca como desejasse.
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

MVVM - Using bindings and handling the captlers in the ViewModel (Recommended).

In this case, the searchbar declaration in XAML would be cleaner and decoupled (in addition to not needing ValueConverter ):

<SearchBar Text="{Binding SearchText}"
           SearchCommand="{Binding SearchCommand}"/>

Your ViewModel would treat the data received in the invocation of the search command (that is, in the ExecuteSearch method) as you wish. In that case this part of the logic would be totally transparent to the user (and to the view) and his business rule would be 'testable':

private void ExecuteSearch()
{
    var texto = SearchText?.ToUpper();

    if(!string.IsNullOrWhiteSpace(texto))
    {
        // Aqui você faria a busca como desejasse.
    }
}

I hope I have helped.

    
15.05.2018 / 20:59