Search code examples
xamarinxamarin.formscross-platformmvvmcrosspicker

Picker not select xamarin


I have on a 3-screen Picker, but let's just review one of them first based on the video below.

In my Model view I have.

public ObservableCollection<string> DadosPessoa { get; }
private dbo_registro_dado _dado;
        public dbo_registro_dado Dado
        {
            get => _dado;
            set => SetProperty(ref _dado, value);
        }
public AddDadosViewModel(dbo_registro_dado registro)
        {
var contentsPessoa = await App.DadosRepo.GetAllDadosPessoaAsync();
            DadosPessoa.Clear();
            foreach (var d in contentsPessoa)
            {
                DadosPessoa.Add(d.nomePessoa);
            }
Dado = registro;
}

In my page xaml

 <Label Text="{Binding Dado.pessoa}" ></Label>
<Picker Title="Pessoa" ItemsSource="{Binding DadosPessoa}" SelectedItem="{Binding Dado.pessoa}"  />

When I call and screen, at certain times appears selected and at certain times does not appear, see in the videos that I added a Label above the picker only to be sure what information is appearing

it will be because of the data loading delay, what can I do to resolve this?

remembering that the data that fills the picker comes from an internal sqlite base

https://www.youtube.com/watch?v=1OVnc_BMuZ8


Solution

  • The correct way for a View to wait for an async operation in a ViewModel is to put the call to the async operation in a method of the ViewModel that is marked as async and return a Task:

    public async Task LoadDataAsync(dbo_registro_dado registro)
    {
            var contentsPessoa = await App.DadosRepo.GetAllDadosPessoaAsync();
            DadosPessoa.Clear();
            foreach (var d in contentsPessoa)
            {
                DadosPessoa.Add(d.nomePessoa);
            }
            Dado = registro;
    }
    

    then from the View call the async method, awaiting for it:

    await vm.LoadDataAsync(registro);
    

    where vm is a reference to your ViewModel, registro the argument you need to pass.

    If you don't instantiate the ViewModel yourself (e.g. you use dependency injection), or if you instantiate it in the constructor of your View (where you cannot use the await keyword) then you can override the OnBindingContextChanged method, like this:

    protected override async void OnBindingContextChanged()
        {
            if (BindingContext is YourViewModel vm) {
                await vm.LoadDataAsync();
            }
            base.OnBindingContextChanged();
        }
    

    Honestly, I doubt that the code you posted can compile, because you try to await for an async operation in a method that is not marked as async. Furthermore, if AddDadosViewModel is the constructor of your ViewModel, yon cannot mark it as async, because you cannot mark a constructor as async.

    Anyway, try to implement the pattern I explained here, it should work.