【问题标题】:How to set listview itemssource to a viewmodel in Xamarin?如何在 Xamarin 中将 listview itemssource 设置为 viewmodel?
【发布时间】:2019-08-10 14:16:19
【问题描述】:

我正在尝试在 xamarin 中创建一个列表视图来显示来自 restapi 的数据,但可以选择过滤列表或根据姓氏对其进行排序。

我已将 bindingcontext 设置为等于有效的 apiviewmodel。但我想将 itemssource 设置为稍后可以操作的列表,而不是绑定上下文。

这是有效的代码:

Xaml:

<ListView x:Name="DirectoryListView" ItemsSource="{Binding ContactsList}" IsPullToRefreshEnabled="True">

Xaml.cs:

LocalAPIViewModel = new APIViewModel();
BindingContext = LocalAPIViewModel;

APIViewModel.cs:

private List<MainContacts> _ContactsList { get; set; }
public List<MainContacts> ContactsList
    {
        get
        {
            return _ContactsList;
        }
        set
        {
            if(value != _ContactsList)
            {
                _ContactsList = value;
                NotifyPropertyChanged();
            }
        }
    }

public class MainContacts
{
    public int ID { get; set; }
    public string FirstName { get; set; }
}

这一切都很好。只有当我添加以下行时,它才会停止在列表视图中显示数据:

xaml.cs:

LocalList = LocalAPIViewModel.ContactsList;
DirectoryListView.ItemsSource = LocalList;

我想我需要添加这些行,以便我可以操作正在显示的列表。为什么不显示列表?这不应该是这样吗?

【问题讨论】:

  • 为什么要添加这些行?它完全违反了 MVVM 架构。此外,您基本上是在将相同的数据源重新分配给 ListView,这没有任何意义。你想达到什么目标?
  • 如您所知,我对此很陌生。我希望能够使用搜索栏搜索列表,并按名字或姓氏对其进行排序。我还希望能够单击其中一个联系人并打开有关该联系人的单独页面。
  • @Ryan,我做了一个可以满足你要求的样品,请看看我的回复更新。
  • @Ryan,你不需要添加那些行,我使用 BindingContext 做示例,可以接受你的要求,你可以看看我的更新。

标签: c# xamarin viewmodel


【解决方案1】:

根据你的描述和代码,你先用MVVM绑定ListView,效果很好,现在你想用Viewmodel直接绑定xaml.cs中的ListView itemsource,对吗?

如果是,我按照你的代码做一个示例,你可以看看,数据可以成功显示。

public partial class Page4 : ContentPage
{
    public APIViewModel LocalAPIViewModel { get; set; }
    public Page4 ()
    {
        InitializeComponent ();
        LocalAPIViewModel = new APIViewModel();           
        listview1.ItemsSource = LocalAPIViewModel.ContactsList;
    }
}

public class APIViewModel
{
    public ObservableCollection<MainContacts> ContactsList { get; set; }
    public APIViewModel()
    {
        loadddata();
    }

    public void loadddata()
    {
        ContactsList = new ObservableCollection<MainContacts>();
        for(int i=0;i<20;i++)
        {
            MainContacts p = new MainContacts();
            p.ID = i;
            p.FirstName = "cherry"+i;
            ContactsList.Add(p);
        }
    }
}
public class MainContacts
{
    public int ID { get; set; }
    public string FirstName { get; set; }
}

所以我建议你可以检查 ContactsList 是否有数据。

更新:

我希望能够使用搜索栏搜索列表并按名字或姓氏对其进行排序。我还希望能够单击其中一个联系人并打开有关该联系人的单独页面

我做了一个可以满足你要求的样品,你可以看看:

https://github.com/851265601/xf-listview

【讨论】:

  • 感谢您的回答!请您查看我最初的问题,如果它很好,请点赞,如果不好,请告诉我如何改进它!
【解决方案2】:

所以,回答你所有的问题...


首先是绑定。

一旦您设置了ItemsSource="{Binding ContactsList}",这意味着无论何时您通过调用OnPropertyChanged() 表明您已更改您的ContactsList,这将反映在ItemsSource 属性上(因此,更新用户界面 - 即这就是我们将OnPropertyChanged() 放入setter 的原因)。因此,您无需在每次更改时手动设置ItemsSource。 (尤其是 View,因为 View 不应该知道 ContactsList 在 ViewModel 中是如何定义的。)

因此,您可以从 View 的代码隐藏中完全删除这些行。


接下来是排序和搜索。

OnPropertyChanged() 所做的是,它从 ViewModel 重新请求绑定的属性,并据此更新 View。所以,就在调用OnPropertyChanged() 之后,View 调用了绑定属性(ContactsList)的getter。

所以,一个好主意是将排序机制放入公共属性的 getter 中。 (或设置器,重置属性时。)像这样:

public class ViewModel {
    private ObserveableCollection<MainContacts> contactList { get; set; }
    public ObserveableCollection<MainContacts> ContactList {
        get {
            return new ObservableCollection<MainContacts>(contactList
                .Where(yourFilteringFunc)
                .OrderBy(yourOrderingFunc));
        }
        set {
            contactsList = value;
            OnPropertyChanged();
        }
    }
    //...
}

因此,无论何时调用您的公共属性,它都会对私有属性进行排序并以这种方式返回集合。

【讨论】:

  • 这真的很有帮助!请你看看我原来的问题,如果它很好,那么就投赞成票,如果它不好,那么让我知道如何改进它!
【解决方案3】:

public List&lt;MainContacts&gt; ContactsList 更改为public ObservableCollection&lt;MainContacts&gt; ContactsList

xaml.cs

而不是LocalList = LocalAPIViewModel.ContactsList;,放

ContactsList = new ObservableCollection(LocalAPIViewModel.ContactsList);

我认为这会起作用,而不是将 ListView 的 Itemsource 设置为 'LocalList'

【讨论】:

  • 将此行添加到 xaml.cs 时出现以下错误 - 当前上下文中不存在 ContactsList 并且 ObservableCollection 需要 1 个类型的参数
猜你喜欢
  • 2020-06-29
  • 1970-01-01
  • 2017-01-05
  • 1970-01-01
  • 1970-01-01
  • 2017-04-06
  • 1970-01-01
  • 2012-10-14
  • 2015-11-19
相关资源
最近更新 更多