Xamarin表单选项卡式页面无法从OnAppearing中检索数据 [英] Xamarin forms tabbed page not retrieving data from in OnAppearing

查看:88
本文介绍了Xamarin表单选项卡式页面无法从OnAppearing中检索数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从Azure数据库检索数据以显示选项卡式页面之一.在OnAppearing中从ViewModel调用该方法时,不是检索数据,而是单击按钮检索并显示在页面上.

I retrieve data from the Azure database to show one of the tabbed pages. when calling the method from ViewModel in OnAppearing not retrieve data, but when click the button it retrieves and shows on the page.

请咨询我是否已构建ViewModel并正确查看?如果是这样,为什么它不起作用. ?

Please advice If I have constructed ViewModel and view correctly? if so why it doesn't work. ?

连接管理器:

    public partial class DatabaseManager
    {
    static DatabaseManager defaultInstance = new DatabaseManager();
    MobileServiceClient client;
    IMobileServiceTable<Person> personTable;

    private DatabaseManager()
    {
        this.client = new MobileServiceClient(Constants.AzureMobileAppURL);

        this.personTable = client.GetTable<Person>();
    }

    public static DatabaseManager DefaultManager
    {
        get
        {
            return defaultInstance;
        }
        private set
        {
            defaultInstance = value;
        }
    }

    public MobileServiceClient CurrentClient
    {
        get { return client; }
    }
  }

型号:

   public class Person
   {
     [JsonProperty(PropertyName = "FirstName")]
    public string FirstName
    {
        get { return firstName; }
        set { firstName = value; }
    }

    [JsonProperty(PropertyName = "DisplayName")]
    public string DisplayName
    {
        get { return displayName; }
        set { displayName = value; }
    }

    [JsonProperty(PropertyName = "LastName")]
    public string LastName
    {
        get { return lastName; }
        set { lastName = value; }
    }
   }

ViewModel:

ViewModel:

     public class ProfilePageViewModel : ViewModelBase
     {
    DatabaseManager manager;
    string firstName = "";
    string lastName = "";
    string displayName = "";;
    IMobileServiceTable<Person> personTable;

     public ProfilePageViewModel()
     {
       manager = DatabaseManager.DefaultManager;
        this.personTable = manager.CurrentClient.GetTable<Person>();

        RefreshCommand = new Command(
            execute: async () =>
            {
                try
                {
                    await GetProfileAsync();
                }
                catch
                {

                }

            });
          }

      public async Task GetProfileAsync()
       {
        try
        {

            IEnumerable<Person> items = await personTable
               .Where(pserson => pserson.Active)
               .ToEnumerableAsync();

            foreach (var item in items)
            {
                FirstName = item.FirstName;
                LastName = item.LastName;
                DisplayName = item.DisplayName;

            }

        }
        catch (Exception e)
        {

        }
       }

    public string FirstName
    {
        private set { SetProperty(ref firstName, value); }
        get { return firstName; }
    }

    public string LastName
    {
        private set { SetProperty(ref lastName, value); }
        get { return lastName; }
    }

    public string DisplayName
    {
        private set { SetProperty(ref displayName, value); }
        get { return displayName; }
    }

   public ICommand RefreshCommand { private set; get; }
 }

查看:

  ProfilePage.xaml
 <?xml version="1.0" encoding="utf-8" ?>
 <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         x:Class="SLSNZ.Views.ProfilePage"
         xmlns:controls="clr- 
             namespace:ImageCircle.Forms.Plugin.Abstractions;
             assembly=ImageCircle.Forms.Plugin"
             xmlns:local="clr-namespace:SLSNZ.ViewModels"
             Title="Profile">

  <ContentPage.Resources>
    <ResourceDictionary>
        <local:ProfilePageViewModel x:Key="viewModel">

        </local:ProfilePageViewModel>
    </ResourceDictionary>
  </ContentPage.Resources>

<ContentPage.Icon>
    <OnPlatform x:TypeArguments="FileImageSource">
        <On Platform="iOS" Value="icon-profile.png" />
    </OnPlatform>
</ContentPage.Icon>

<ContentPage.Padding>
    <OnPlatform x:TypeArguments="Thickness"                     
                iOS="0, 20, 0, 0" />
</ContentPage.Padding>

    <StackLayout BindingContext="{StaticResource viewModel}">
    <Label Text="Display Name"
               TextColor="Gray"
               FontSize="Small"                
               HorizontalOptions="Start" /> 

    <Label Text="{Binding DisplayName}" 
                VerticalOptions="Center"
               HorizontalOptions="Start"                
               VerticalOptions="Start/>

     <Label Text="First Name"
               TextColor="Gray"
               FontSize="Small"                
               HorizontalOptions="Start" />

     <Label Text="{Binding FirstName}"              
               FontSize="Large" 
               HorizontalOptions="Start"                
               VerticalOptions="Start" />

     <Label Text="Last Name"  
               TextColor="Gray"
               FontSize="Small"                
               HorizontalOptions="Start" />

     <Label Text="{Binding LastName}"              
               FontSize="Large"                
               HorizontalOptions="Start"                
               VerticalOptions="Start" /> 

     <Button Text="Refresh"
                        Command="{Binding RefreshCommand}"
                        Grid.Row="0" Grid.Column="1"/>

    </StackLayout>
    </ContentPage>

查看:

  ProfilePage.cs

  public partial class ProfilePage : ContentPage
   {
  ProfilePageViewModel viewModel;

  public ProfilePage()
    {
        InitializeComponent();
        viewModel = new ProfilePageViewModel();

    }

   protected override async void OnAppearing()
    {

        base.OnAppearing();
        await viewModel.GetProfileAsync();
    }
  }

ViewModelBase:

ViewModelBase:

 public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected bool SetProperty<T>(ref T storage, T value,
                                  [CallerMemberName] string propertyName = 
    null)
    {
        if (Object.Equals(storage, value))
            return false;

        storage = value;
        OnPropertyChanged(propertyName);
        return true;
    }

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

推荐答案

在您等待viewModel.GetProfileAsync()之前在您的视图中该视图将已经呈现.

In your view by the time you await viewModel.GetProfileAsync(); The view will already render.

您的视图模型中的GetProfileAsync会等待,因此将获取数据,然后对其进行更新.

Your GetProfileAsync in the View Model does an await so will get the data then update it.

我建议将IMobileServiceTable personTable更改为属性,并实施on Property更改以通知视图数据已更改.

I suggest changing the IMobileServiceTable personTable to a property and implement a on Property change to notify the view that the data has changes.

因此您的视图模型应实现INotifyPropertyChanged

So your viewmodel should implement INotifyPropertyChanged

 public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName] string name = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }

然后,当数据更改时,您可以在视图模型中通知它,例如:

Then when the Data Changes you can notify it in the view model like:

OnPropertyChanged("personTable");

在您看来,也将代码更改为:

Also in your view change your code to:

预初始化视图模型:

public ProfilePage()
    {
        InitializeComponent();

         SetViewModel();

    }

   protected async void SetViewModel()
    {  
       viewmodel = await viewModel.GetProfileAsync();
    }

这样,您将不会阻塞UI线程,并且在调用OnPropertyChnage时,它将通知您的视图进行更新.

This way you wont block the UI thread and when you call the OnPropertyChnage it will notify your view to update.

更新:

我为您创建了一个小样本Xamarin项目,以演示如何绑定并通知更改视图.

I have created a small sample Xamarin project for you to demonstrate how you can bind and notify the view of changes.

视图中还存在一些问题,其中DisplayName标签未正确关闭,某些标签中Horizo​​ntalOptions的属性重复.

You had a few issues in your view as well where your DisplayName label was not closed properly and you had duplicate properties for HorizontalOptions in some labels.

下载此Xamarin示例.它具有硬编码的数据,但是将向您展示设置数据的流程和视图的绑定上下文,而无需锁定UI线程.

Download this Xamarin sample. It had hard coded data but will show you the flow of setting the data and the Binding Context of the View without locking the UI thread.

https://github.com/loanburger/54430503

这篇关于Xamarin表单选项卡式页面无法从OnAppearing中检索数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆