【问题标题】:Bind data collection on xamarin using mvvm使用 mvvm 在 xamarin 上绑定数据收集
【发布时间】:2017-12-18 22:23:19
【问题描述】:

所以我开始学习 xamarin 并尝试不同的方法来将数据绑定从视图到模型。我正在使用发布请求从服务中检索数据,在获得数据后,我无法将它们绑定到视图。经过大量研究,我找到了一些有趣的解决方案,并尝试了不同的方法。 这是我到目前为止所取得的成就: 我的看法:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         x:Class="Ideas.Pages.IdeasSinglePage"
         xmlns:vm="clr-namespace:Ideas.ViewModel;assembly=Ideas"
          Title="My idea">

<ContentPage.BindingContext>
    <vm:IdeasViewModel/>
</ContentPage.BindingContext>

<StackLayout>
    <Button Command="{Binding GetIdeasCommand}"
            Text="Bileta Ime"
            TextColor="White"
            FontSize="15"
            BackgroundColor="#29abe2"/>
    <Label Text="test"></Label>

    <ListView ItemsSource="{Binding Ideas}"
              HasUnevenRows="True">

        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout Padding="20, 10">
                        <Label  Text="{Binding IdeasName}"
                                 FontSize="16"
                               TextColor="RoyalBlue"/>

                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

</StackLayout>

这是我的视图模型

public class IdeasViewModel : INotifyPropertyChanged
{
    ApiServices _apiServices = new ApiServices();
    public List<Ideas> Ideas
    {
        get { return Ideas; }
        set
        {
            Ideas= value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public ICommand GetIdeasCommand
    {
        get
        {
            return new Command(async () =>
            {
                Ideas= await _apiServices.GetIdeasAsync();
            });
        }
    }


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

}

这是我的服务:

public async Task<List<Ideas>> GetIdeasAsync()
    {
        ListIdeasDetails ideas= null;
        try { 
            var client = new HttpClient();
            client.DefaultRequestHeaders.Add("parameter", "parameter");
            client.DefaultRequestHeaders.Add("parameter", parameter);

            HttpContent content = new StringContent("");
            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

            var response = await client.PostAsync("https://heregoes/themethod", content);
            response.EnsureSuccessStatusCode();
            string json = await response.Content.ReadAsStringAsync();
            ideas= JsonConvert.DeserializeObject<ListIdeasDetails>(json);
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message.ToString());
        }
        return ideas.Ideas;
    }
}

这是我的两个模型:

public class Ideas
{

    public string IdeasID  { get; set; }

    public string IdeasName  { get; set; }
 }


class ListIdeasDetails
{
    public List<Ideas> Ideas{ get; set; }
    public string ExceptionMessage { get; set; }
    public bool HasException { get; set; }

}

非常感谢您的帮助!谢谢!!

【问题讨论】:

  • 我建议将 List 更改为 Observablecollection
  • @dilmah 我认为这不会有太大变化。我的意思是我的代码对你来说还可以吗?还是我错过了什么?因为从 apiservice 获取 json 后,我一直得到一个空视图。
  • @Aldo 您确定您的服务实际上返回了任何数据吗?设置一个断点并首先查看您的 Web 请求返回的内容。其次,在你的虚拟机设置器中设置一个断点,看看它是否被调用过。题外话:使用 POST 网络请求下载数据感觉很臭。
  • @EvZ 当然我敢肯定。我已经尝试过了,我收到了一个包含我需要的所有数据的 json。我似乎无法理解为什么我的观点是空的?! ://

标签: c# xamarin mvvm xamarin.forms models


【解决方案1】:

您的property definition 似乎有问题:

 public List<Ideas> Ideas
 {
    get { return Ideas; }
    set
    {
        Ideas= value; // Endless loop
        OnPropertyChanged();
    }
 }

以这种方式添加支持字段:

List<Ideas> _ideas;
public List<Ideas> Ideas
{
    get { return _ideas; }
    set
    {
        if(value == _ideas) return;
        _ideas = value;
        OnPropertyChanged();
    }
}

我建议使用Fody.PropertyChanged 以减少与 INotifyPropertyChanged 相关的样板代码量。使用 Fody 你的 ViewModel 看起来很简单:

public class IdeasViewModel : INotifyPropertyChanged
{
    ApiServices _apiServices = new ApiServices();
    public List<Ideas> Ideas { get;set; }

    public event PropertyChangedEventHandler PropertyChanged;

    public ICommand GetIdeasCommand
    {
        get
        {
            return new Command(async () =>
            {
                Ideas= await _apiServices.GetIdeasAsync();
            });
        }
    }
}

P.S.:除了您的主要问题之外,我想指出您的代码中看起来不太好的下一个问题。

  1. 使用 POST 从 WEB 下载数据。
  2. 类名“ApiServices”。

如果您需要进一步的帮助,可以通过评论告诉我。

【讨论】:

  • 当然,它就像一个魅力。我无法相信我所犯的错误。我总是以无限循环结束。非常感谢@evz :)
  • 欢迎来到 stackoveflow,请花 1 分钟时间查看:stackoverflow.com/help/someone-answers
  • 我使用的 api 只允许发布请求。那么在这种情况下我能做些什么呢?类名“ApiServices”有什么问题?
  • 这取决于你的上下文,然而,创建一个类来定义单个对象是很常见的,如果你需要一个对象的集合,通常使用集合。因此,当您以复数形式命名“ApiServices”类时,它可能会识别出一些问题。你真的在一个类中定义了多个服务吗?如果没有,只需将其重命名为“ApiService”。否则,您可以将其划分为单独的类。关于API,如果是这样写的,而且你没有权限访问源代码,那你就无能为力了。
  • 我在“ApiServices”类中有不同的服务,这就是我这样命名的原因。关于api,我无能为力。我能问你一件事吗?如果除了我想导航到另一个页面的数据之外单击按钮并且我想使用另一个页面上的数据,您能否为我提供解决方案?!我该如何解决这个问题?!我尝试添加`Branches = await _apiServices.GetBranchesAsync();等待 Application.Current.MainPage.Navigation.PushAsync(new TicketSinglePage());` 但它似乎不起作用。提前感谢@evz
猜你喜欢
  • 2018-08-14
  • 2019-07-13
  • 1970-01-01
  • 1970-01-01
  • 2022-01-18
  • 2021-11-05
  • 2018-02-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多