Привязать текстовое поле к значению, которое извлекается из REST Api с помощью Xamarin

#c# #android #.net #iphone #xamarin

#c# #Android #.net #iPhone #xamarin

Вопрос:

Я запустил проект Xamarin, используя шаблон, доступный в Visual Studio. Я написал несколько сервисов, которые извлекают данные из REST api. Я распечатал эти значения на консоли, и я могу видеть, что службы работают так, как должны.

Однако у меня возникают проблемы с отображением имени пользователя, которое я извлек из Api. Я пытаюсь сделать это в классе ViewModel.

 using MyApp.Models;
using System;
using System.Windows.Input;
using Xamarin.Essentials;
using Xamarin.Forms;
using MyApp.Services;
using System.Threading.Tasks;

namespace MyApp.ViewModels
  {
   public class AboutViewModel : BaseViewModel
    {
    static readonly UserService CurrentUser = new UserService();

    public AboutViewModel()
    {
        //GetData().Wait();
        Title = "My App";
        OpenWebCommand = new Command(async () => await Browser.OpenAsync("https://aka.ms/xamain-quickstart"));
        IsConnected = false;
        GetData();
    }

    protected async void GetData()
    {
        user = await CurrentUser.GetUser();
        Name = user.fullName;
    }

    public ICommand OpenWebCommand { get; }
    public bool IsConnected { get; set; }
    public string Name { get; set; }
    public User user { get; set; }
}
}
  

Это строка из файла .xaml, где оно будет отображаться:

 <Label Text="{Binding Name}" FontSize="Title"/>
  

Я знаю, что это плохая практика, но я попытался заставить его работать. Он по-прежнему не работает и ничего не отображает. Это единственное, что мне удалось до сих пор, что не приводит к сбою или зависанию приложения. Как привязать к переменной «Name», когда «Name» в конечном итоге будет установлено из асинхронной void или задачи?

Комментарии:

1. 1) устанавливаете ли вы BindingContext для своей страницы на виртуальной машине? 2) если вы загружаете свои данные после загрузки страницы, ваша виртуальная машина должна реализовать INotifyPropertyChanged

Ответ №1:

BaseViewModel Вероятно, вам следует реализовать INotifyPropertyChanged интерфейс или наследовать от класса, который его уже реализует, если вы используете своего рода фреймворк MVVM.

Это может выглядеть примерно так:

 public class BaseViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged([CallerMemberName]string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    protected bool SetProperty<T>(ref T backingField, T newValue, [CallerMemberName] string propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(backingField, newValue))
        {
            return false;
        }

        backingField = newValue;
        RaisePropertyChanged(propertyName);
        return true;
    }
}
  

Затем для ваших свойств в вашей ViewModel, которые вы могли бы использовать SetProperty , чтобы убедиться PropertyChanged , что они срабатывают при изменении их значений. Это необходимо для пользовательского интерфейса, к которому они привязаны, чтобы выяснить, что что-то изменилось.

 private string _name;
public string Name
{
    get => _name;
    set => SetProperty(ref _name, value);
}
  

Если вы не хотите использовать SetProperty , просто используйте RaisePropertyChanged :

 private string _name;
public string Name
{
    get => _name;
    set
    {
        _name = value;
        RaisePropertyChanged();
    }
}
  

Комментарии:

1. Я посмотрел, как другие переменные были объявлены в BaseViewModel с некоторыми дополнительными элементами. Итак, в основном, как вы сделали здесь. Теперь это работает. Спасибо!