【问题标题】:Populate ListView when page is loaded (Xamarin.Forms) using a Command使用命令加载页面 (Xamarin.Forms) 时填充 ListView
【发布时间】:2017-04-12 22:37:08
【问题描述】:

我尝试在加载页面时填充绑定到 ObservableCollection 的 ListView,但未成功。目前,我使用以下代码使用按钮(绑定到命令)。

查看:

<Button Text="Load Items" Command="{Binding LoadItemsCommand}"></Button>
<ActivityIndicator IsRunning="{Binding IsBusy}" IsVisible="{Binding IsBusy}" />
<ScrollView>
  <ListView ItemsSource="{Binding Items}">      
    .....
  </ListView>
</ScrollView>

View.cs:

private ItemsViewModel _itemsViewModel;

public ItemsView()
{
    InitializeComponent();
    _itemsViewModel = new ItemsViewModel();
    BindingContext = _itemsViewModel;
}

视图模型:

public ObservableCollection<Item> Items{ get; set; }
public Command LoadItemsCommand { get; set; }

public ItemsViewModel()
{
    Items = new ObservableCollection<Item>();
    _isBusy = false;

    LoadItemsCommand = new Command(async () => await LoadItems(), () => !IsBusy);    
}

public async Task LoadItems()
{
    if (!IsBusy)
    {
        IsBusy = true;
        await Task.Delay(3000); 
        var loadedItems = ItemsService.LoadItemsDirectory(); 

        foreach (var item in loadedItems)
            Items.Add(item);

        IsBusy = false;
    }
}

这与按钮完美配合,但我不知道如何自动完成。我尝试将列表视图的 RefreshCommand 属性绑定到我的命令,但没有。

【问题讨论】:

    标签: c# .net mvvm xamarin xamarin.forms


    【解决方案1】:

    有几种方法,但最好的方法是在加载数据的视图模型构造函数中启动一项任务。我也不会将每个项目添加到 observable 集合中,因为这意味着最终添加时会更新 UI。加载完所有数据后,最好完全替换集合。

    类似:

    public ItemsViewModel()
    {
        Items = new ObservableCollection<Item>();
        _isBusy = false;
    
        Task.Run(async () => await LoadItems());    
    }
    
    public async Task LoadItems()
    {
        var items = new ObservableCollection<Item>(); // new collection
    
        if (!IsBusy)
        {
            IsBusy = true;
            await Task.Delay(3000); 
            var loadedItems = ItemsService.LoadItemsDirectory(); 
    
            foreach (var item in loadedItems)
                items.Add(item);                // items are added to the new collection    
    
            Items = items;   // swap the collection for the new one
            RaisePropertyChanged(nameof(Items)); // raise a property change in whatever way is right for your VM
    
            IsBusy = false;
        }
    }
    

    【讨论】:

    • 感谢您的帮助@JimBobBennet。它通过在视图模型的构造函数上启动任务来工作。但是,集合的交换不起作用,它仅在我直接在循环中将项目添加到公共 Items 属性时才起作用。此外,我的印象是没有必要在 ObservableCollections 上调用 PropertyChanged。在我的情况下,它可以在没有那条线的情况下工作
    • 如果您添加到现有集合中,则 UI 将更新,但它会很慢,因为 UI 将为您添加的每个项目重新绘制。对于 1,000 件物品,您将度过一段糟糕的时光。属性更改是因为在我的示例中它将 Items 属性的值替换为全新的集合,因此您需要提高属性更改以告诉它重新加载新集合 - 导致 1 次 UI 更新
    • 知道了!感谢您的澄清@JimBobBennett
    • 感谢@JimBobBennett,它对我也很有效。非常感谢。
    • RaisePropertyChanged 有点令人困惑,如果您可以分享它的实现或引用它所在的类会很棒
    猜你喜欢
    • 2020-09-27
    • 2010-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-25
    • 1970-01-01
    相关资源
    最近更新 更多