#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 с некоторыми дополнительными элементами. Итак, в основном, как вы сделали здесь. Теперь это работает. Спасибо!