【问题标题】:How to display data on UI by calling API in Xamarin如何通过在 Xamarin 中调用 API 在 UI 上显示数据
【发布时间】:2018-12-07 08:14:55
【问题描述】:

我是 Xamarin 的新手并正在开发一个 iOS 应用程序,我需要调用一个 API 并绑定响应数据以查看已使用 MVVM 模式。

这是我的ViewModel 代码:

public class PersonalDetailModel : BaseViewModel
{
    private PersonalDetails personalDetails { get; set; }
    public Command LoadCommand;

    public PersonalDetailModel()
    {
        LoadCommand = new Command(async () => await GetPersonalDetais());

    }
    public String City
    {
        get
        {
            return personalDetails.city;
        }
        set
        {
            personalDetails.city = value;
        }
    }
    public string Phone
    {
        get { return personalDetails.phone; }
        set
        {
            personalDetails.phone = value;

        }
    }
    public string Email
    {
        get { return personalDetails.email; }
        set
        {
            personalDetails.email = value;

        }
    }

    public async Task<PersonalDetails> GetPersonalDetais()
    {
        var ApiRequest = RestService.For<IUserService>(Constants.BaseUrl);

        PersonalDetailsResponse ApiResponse = await ApiRequest.showProfile(Constants.token);

        PersonalDetailsResponse response = ApiResponse;

        this.personalDetails = response.result;
        personalDetails = new PersonalDetails
        {
            city = personalDetails.city,
            phone = personalDetails.phone,
            email = personalDetails.email
        };

        return this.personalDetails;
    }


}

GetPersonalDetais() 中,我在调试过程中从 API 获取值,但我无法在 UI 中绑定该值。

XML 代码:

<?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="BarberCustomer.Views.PersonalDetails"
             >
    <ContentPage.Content>
        <StackLayout Orientation="Vertical" Padding="4,5" BackgroundColor="#efeff4" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
            <Frame HasShadow="True" Padding="8,5,8,12" CornerRadius="2"  Margin="1,1,0,0" HorizontalOptions="FillAndExpand" 
                   VerticalOptions="Start">
                <StackLayout Orientation="Vertical" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
                    <Label Text="Personal Details" HorizontalOptions="Start" VerticalOptions="FillAndExpand" LineBreakMode="WordWrap" FontSize="12" TextColor="#ad0e0e">
                        <Label.FontFamily>
                            <OnPlatform x:TypeArguments="x:String">
                                <OnPlatform.Android>SFProDisplay-Bold.ttf#SF-Pro-Display-Bold</OnPlatform.Android>
                                <OnPlatform.iOS>SFProDisplay-Bold</OnPlatform.iOS>
                            </OnPlatform>
                        </Label.FontFamily>
                    </Label>
                    <StackLayout Margin="0,1,0,1" HorizontalOptions="FillAndExpand" HeightRequest="1" BackgroundColor="#efeff4" VerticalOptions="EndAndExpand" Padding="0">
                    </StackLayout>
                    <StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" VerticalOptions="Center">
                        <Image Source="location.png" WidthRequest="8" HeightRequest="11" VerticalOptions="Center" Aspect="AspectFit" ></Image>
                        <Label Text="{Binding City}" Margin="4,0,0,0"
                               HorizontalOptions="Start" VerticalOptions="FillAndExpand" LineBreakMode="WordWrap" FontSize="9" TextColor="#253045">
                            <Label.FontFamily>
                                <OnPlatform x:TypeArguments="x:String">
                                    <OnPlatform.Android>SFProDisplay-Medium.ttf#SFProDisplay-Medium</OnPlatform.Android>
                                    <OnPlatform.iOS>SFProDisplay-Medium</OnPlatform.iOS>
                                </OnPlatform>
                            </Label.FontFamily>
                        </Label>

                    </StackLayout>

                    <StackLayout HorizontalOptions="FillAndExpand" HeightRequest="1" BackgroundColor="#eeeeee" VerticalOptions="EndAndExpand" Padding="0" Margin="17,1,0,1">

                    </StackLayout>
                    <StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" VerticalOptions="Center">
                        <Image Source="phone.png" WidthRequest="8" HeightRequest="11" VerticalOptions="Center" Aspect="AspectFit" ></Image>
                        <Label Text="{Binding Phone}" Margin="4,0,0,0"
                               HorizontalOptions="Start" VerticalOptions="FillAndExpand" LineBreakMode="WordWrap" FontSize="9" TextColor="#253045">
                            <Label.FontFamily>
                                <OnPlatform x:TypeArguments="x:String">
                                    <OnPlatform.Android>SFProDisplay-Medium.ttf#SFProDisplay-Medium</OnPlatform.Android>
                                    <OnPlatform.iOS>SFProDisplay-Medium</OnPlatform.iOS>
                                </OnPlatform>
                            </Label.FontFamily>
                        </Label>
                    </StackLayout>
                    <StackLayout HorizontalOptions="FillAndExpand" HeightRequest="1" BackgroundColor="#eeeeee" VerticalOptions="EndAndExpand" Padding="0" Margin="17,1,0,1">

                    </StackLayout>
                    <StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" VerticalOptions="Center">
                        <Image Source="mail.png" WidthRequest="11" HeightRequest="12" VerticalOptions="Center" Aspect="AspectFit" ></Image>
                        <Label Text="{Binding Email}" Margin="4,0,0,0"
                               HorizontalOptions="Start" VerticalOptions="FillAndExpand" LineBreakMode="WordWrap" FontSize="9" TextColor="#253045">
                            <Label.FontFamily>
                                <OnPlatform x:TypeArguments="x:String">
                                    <OnPlatform.Android>SFProDisplay-Medium.ttf#SFProDisplay-Medium</OnPlatform.Android>
                                    <OnPlatform.iOS>SFProDisplay-Medium</OnPlatform.iOS>
                                </OnPlatform>
                            </Label.FontFamily>
                        </Label>
                    </StackLayout>
                </StackLayout>
            </Frame>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

xml.cs:

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class PersonalDetails : ContentPage
{
    PersonalDetailModel viewModel;

    public PersonalDetails()
    {
        InitializeComponent();

        viewModel = new PersonalDetailModel();

        BindingContext = viewModel;



    }

    protected async override void OnAppearing()
    {
        base.OnAppearing();
        viewModel.LoadCommand.Execute(null);

    }
}

我们将不胜感激每一个回复和建议!

【问题讨论】:

  • 绑定数据的按钮在哪里??是另一种观点吗?或者您是否尝试使用您的按钮将数据绑定在同一个视图中?
  • @IdevDev 在同一个视图上
  • 你只有这个xml吗?你能分享一下xaml.cs吗?这样我们可以更好地了解情况?
  • @IdevDev 查看我的编辑!
  • @SMM,你是如何将 API 调用与 ViewModel 分开的?我无法从 var ApiRequest = RestService.For(Constants.BaseUrl); 行中理解

标签: xaml xamarin.ios async-await


【解决方案1】:

您应该将 BindingContext 放在 xaml.cs 或 xaml 中以将您的 ViewModel 与 View 绑定。

有多种方法可以将数据绑定到您的视图。

ViewModel.cs

public class PettyCashListViewModel : BaseNavigationViewModel

Page.Xaml.cs

public partial class PettyCashListPage : ContentPage
{
    protected PettyCashListViewModel ViewModel => BindingContext as PettyCashListViewModel;

或在您的页面构造函数中

this.BindingContext = ViewModel;

或在您的 page.xaml 中

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:viewModels="clr-namespace:XamarinPOC.ViewModel; assembly=XamarinPOC.ViewModel"
         x:Class="XamarinPOC.Summary"
         Title="Summary List">
     <ContentPage.BindingContext>
        <viewModels:SummaryViewModel/>
     </ContentPage.BindingContext>
     <StackLayout>
        <Label Text="{Binding test}"/>
     </StackLayout>
   </ContentPage>

参考:Set BindingContext to ViewModel in XAML on Xamarin.Forms

【讨论】:

  • 我也面临同样的问题..您能否提供一个更好的描述性答案或添加一些代码(如果可能)
  • @PrashantPimpale,我已经相应地编辑了我的答案。希望这会有所帮助。
【解决方案2】:

我第二个 Selvarathinams 回答。 还要确保您的模型实现了 INotifyPropertyChanged 接口。

你应该添加

public event PropertyChangedEventHandler PropertyChanged;

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

到您的模型类(除非它已经在您的模型派生的基类中实现)。然后在所有设置器中调用 NotifyPropertyChange("propertyName)。

例如:

public string Email
{
    get { return personalDetails.email; }
    set
    {
        personalDetails.email = value;
        NotifyPropertyChanged("Email");
    }
}

这将确保您的视图收到模型值已更改的通知。

还可以尝试在 UI 线程中更新模型值。 为此,在处理异步方法的结果时,请执行以下操作:

Xamarin.Forms.Device.BeginInvokeInMainThread( () => {
    model.City = personalDetails.city;
    model.Phone = personalDetails.phone;
    model.Email = personalDetails.email;
}

如果这不起作用,您可以稍微更改 OnAppearing 中的方法:

protected async override void OnAppearing()
{
    base.OnAppearing();
    PersonalDetails details = await model.GetPersonalDetais();
    Xamarin.Forms.Device.BeginInvokeInMainThread( () => {
        model.City = personalDetails.city;
        model.Phone = personalDetails.phone;
        model.Email = personalDetails.email;
    }
}

说到,我个人觉得检索数据的方法是模型类的一部分有点奇怪。 它将在名为 DataService 的静态类中实现这样的方法,该类包含用于检索数据并保持模型干净的所有方法,以便它只包含需要绑定到视图的数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多