Atlantis
Atlantis

Reputation: 775

Xamarin.Forms set focus from mvvm ViewModel

I'm working on a chat application using Xamarin.Forms.

And I want to avoid to hide the keyboard when the Entry loses focus and button Send is clicked.

How can I do it on Android and iOS?

I use XF, full Mvvm without XAML(only C#)

Updated:

In page class:

private EntrySetBorder _newMessageEntry;
...
_newMessageEntry = new EntrySetBorder
{
    TextColor = Color.Black,
    HorizontalOptions = LayoutOptions.FillAndExpand,
    VerticalOptions = LayoutOptions.End,
    Margin = new Thickness(0, 0, 5, 0)
};

In model class:

var entry = CurrentPage.FindByName<EntrySetBorder>("_newMessageEntry");
entry.Focus();

}

Upvotes: 4

Views: 7994

Answers (2)

CarLoOSX
CarLoOSX

Reputation: 525

This is an example of how I do, before this I used to do using MessagingCenter

in xaml , you need to give an x:Name to the obj you want to make focus.

<!-- PICKER's DEFINITION -->
<DatePicker
    x:Name="Datepicker"
    Date="{Binding SelectedDate, Mode=TwoWay}"
    IsEnabled="true"
    IsVisible="false">
</DatePicker>

then you have to make reference to that control in your command parameter on a button or for example in this case I use a toolbar item.

<!-- MENU TOOLBAR -->
<ContentPage.ToolbarItems>
    <ToolbarItem
        Command="{Binding ShowCalendarCommand}"
        Icon="Calendar"
        CommandParameter="{x:Reference Datepicker}" />
</ContentPage.ToolbarItems>

then in your vm command :

    #region toolbar commands

    public ICommand ShowCalendarCommand => new RelayCommand<Object>(ShowCalendar);

    #endregion

    private void ShowCalendar(Object obj)
    {
        var calendar = (DatePicker)obj;
        calendar.Focus();
        //  MessagingCenter.Send(this, "Calendar");
    }

Upvotes: 1

Paul Karam
Paul Karam

Reputation: 4245

This can be achieved easily by using the FindByName<>() function inside the PCL.
This is one way of doing that:

Entry myEntry = CurrentPage.FindByName<Entry>("YourEntryName");
myEntry.Focus();

You can add that at the end of the click handler of your send button.

Edit:

In your case I think your problem is that your entry is set to private, so I would suggest either expose it as public or expose it using another public property. Two solutions that might work:

public EntrySetBorder _newMessageEntry;
...
_newMessageEntry = new EntrySetBorder
{

    TextColor = Color.Black,
    HorizontalOptions = LayoutOptions.FillAndExpand,
    VerticalOptions = LayoutOptions.End,
    Margin = new Thickness(0, 0, 5, 0)
};

And:

EntrySetBorder entry = CurrentPage.FindByName<EntrySetBorder>("_newMessageEntry");
entry.Focus();

Or you go with this:

private EntrySetBorder _newMessageEntry;
...
_newMessageEntry = new EntrySetBorder
{

    TextColor = Color.Black,
    HorizontalOptions = LayoutOptions.FillAndExpand,
    VerticalOptions = LayoutOptions.End,
    Margin = new Thickness(0, 0, 5, 0)
};
public EntrySetBorder NewMessageEntry => _newMessageEntry;

and :

EntrySetBorder entry = CurrentPage.FindByName<EntrySetBorder>("NewMessageEntry");
entry.Focus();

Please try that :)

Edit 2:

After reviewing your code, and testing it, the final way to fix it was by sending the Entry as a parameter in the command you're using, example:

Inside the page you're creating:

sendButton.CommandParameter = NewMessageEntry; // We're adding the Entry we want to focus as a command parameter.

And inside your PageModel and the command we want to use:

public Command SendCommand
{
    get
    {
        return new Command<Entry>((obj) => //obj here means the parameters we're sending I.E: the entry we set it in the page.
        {
            //The code you want to execute
            Entry entry = obj;
            entry.Focus();
        });
    }
}

Note that I used Entry because I didn't have all the implementation of your custom entry.

Upvotes: 4

Related Questions