Forum Xamarin Xamarin.Forms

How to get ViewCell object of currently selected item in ListView

LapsusLapsus USMember ✭✭

I would like to focus an Entry field inside my list view of the currently selected row, when some conditions are met. How can I get the ViewCell object of the currently selected row in order to find that entry and call .Focus() on it?

The code should look something like this, but I'm missing this important part:

ViewCell vs = /* get the viewcell of the currently selected row */;
var entry = vs.FindByName<Entry>("myEntry");
entry?.Focus();

Best Answer

  • LapsusLapsus USMember ✭✭
    edited September 2018 Accepted Answer

    I managed to solve my problem by using the following anwser from SO:
    https://stackoverflow.com/questions/48811089/focus-viewcell-entry-on-listview-item-selection/49684722#49684722

    Basically I add UI objects to my ViewModel (for example Entry and Label) and then bind them to ViewCell using the

        <ContentView Grid.Row="1" Grid.Column="1" Content="{Binding LocationEntry}"/>
    

    syntax.
    In this way I can detect .Focused/Unfocused events and call .Focus on certain fields when necessary.

    void ListItemSelected(object sender, SelectedItemChangedEventArgs e)
    {
                var selectedItem = e.SelectedItem as ReceiptRow;
                if (selectedItem != null)
                {
                    //Apply focus to selected item
                    if(selectedItem.CanEdit)
                    {
                        selectedItem.ItemIdEntry.Focus();
                    }
                }
    }
    

Answers

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    Today I have tried to bind the "IsFocused" property to an entry but it does not work...

  • seanydaseanyda GBMember ✭✭✭✭✭

    When you call Focus it doesn't ever work, You have to call it from an event to seem to trigger it properly.

    For example, If you attempted to Focus the Entry in the page OnAppearing event or the ViewCell Appearing event like so

    ViewCell viewCell = new ViewCell();
                viewCell.Appearing += (object sender, EventArgs e) => {
    
                };
    
  • JohnHardmanJohnHardman GBUniversity admin

    A bulletproof means of setting Focus that works across platforms has a few fiddly bits. However, for the most common scenario, having a Task.Delay before setting the Focus (ensuring that is done on the UI thread) will do the trick. Inevitably, a Task.Delay introduces a race condition, so a balance has to be found between reducing the chances of hitting the race condition and the UI's responsiveness.

    @Lapsus - In terms of identifying the ViewCell - if Tapped will be sufficient rather than Selected, just override OnTapped in the ViewCell. If Tapped is insufficient, then you'll probably want to add a property to your item's View Model, have the ListView's ItemSelected handler update that property. Have the code-behind for the ViewCell implement a PropertyChanged handler, so that when the property is updated the code-behind sets the focus as described above.

  • LapsusLapsus USMember ✭✭

    @JohnHardman OnTapped is not sufficient, since row selection will not be done only by touch. How can my view model then sets the focus? There isn't anything I can bind the property of my viewModel to. Could you provide a little more info?

    Maybe the solution would be to use OnTapped, and the trigger that event from code if possible?

  • JohnHardmanJohnHardman GBUniversity admin

    @Lapsus said:
    @JohnHardman OnTapped is not sufficient, since row selection will not be done only by touch.

    I support physical keyboards and accessibility, so work with selection, but a scary number of people only work with taps, so I had to raise it as a possibility.

    @Lapsus said:
    How can my view model then sets the focus?

    @JohnHardman said:
    add a property to your item's View Model, have the ListView's ItemSelected handler update that property.

    The View Model doesn't set the focus. The View Model has a property or event that is updated by the ListView's ItemSelected handler. The code-behind for the ViewCell reacts to the change of that property or event, and sets the Focus accordingly.

  • LapsusLapsus USMember ✭✭
    edited September 2018 Accepted Answer

    I managed to solve my problem by using the following anwser from SO:
    https://stackoverflow.com/questions/48811089/focus-viewcell-entry-on-listview-item-selection/49684722#49684722

    Basically I add UI objects to my ViewModel (for example Entry and Label) and then bind them to ViewCell using the

        <ContentView Grid.Row="1" Grid.Column="1" Content="{Binding LocationEntry}"/>
    

    syntax.
    In this way I can detect .Focused/Unfocused events and call .Focus on certain fields when necessary.

    void ListItemSelected(object sender, SelectedItemChangedEventArgs e)
    {
                var selectedItem = e.SelectedItem as ReceiptRow;
                if (selectedItem != null)
                {
                    //Apply focus to selected item
                    if(selectedItem.CanEdit)
                    {
                        selectedItem.ItemIdEntry.Focus();
                    }
                }
    }
    
Sign In or Register to comment.