自定义 ListView 绑定在 Xamarin.Forms 中不起作用

Custom ListView binding not working in Xamarin.Forms

我正在尝试将响应绑定到 Xamarin.Forms 中的自定义 ListView,但即使 ObservableCollection 包含结果,ListView 仍为空白。请指出我在下面代码中的错误。

在下面的代码中,我试图实现以下结果 -

我正在使用 Prism MVVM 架构构建应用程序。

查看

<ListView  ItemsSource="{Binding ListItems}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <Frame BorderColor="LightGray" Padding="5">
                        <StackLayout Orientation="Horizontal">
                            <!--<BoxView BackgroundColor="{Binding HighlightColor}" WidthRequest="10"/>-->
                            <Label Text="{Binding Date}" FontSize="Medium" Margin="20,0,0,0"/>
                            <Label Text="{Binding Day}" FontSize="Medium" Margin="20,0,0,0"/>
                            <Label Text="{Binding LeaveCount}" HorizontalOptions="EndAndExpand" HorizontalTextAlignment="End"/>
                        </StackLayout>
                    </Frame>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

ViewModel

public ObservableCollection<CalendarItem> ListItems { get; set; }    



public LeaveViewerPageViewModel(INavigationService navigationService, IFirebaseService firebaseService)
            : base(navigationService, firebaseService)
        {
            Title = "View Leaves";
            ViewCommand = new DelegateCommand(ViewLeaves);
        }

    private async void ViewLeaves()
    {
        ListItems = new ObservableCollection<CalendarItem>();

        var x = await FirebaseService.GetAll(_month, _year);

        foreach (var item in x)
        {
            ListItems.Add(item);
        }
    }

服务

public async Task<List<CalendarItem>> GetAll( string month, string year)
{
    List<CalendarItem> ItemList = new List<CalendarItem>();

    int iterationLimit = DateTime.DaysInMonth(int.Parse(year), (DateTime.ParseExact(month.Substring(0, 3), "MMM", CultureInfo.InvariantCulture)).Month);

    for (int i = 1; i <= iterationLimit; i++)
    {
       CalendarItem ITEM = new CalendarItem();

        DateTime dateTime = new DateTime(int.Parse(year), DateTime.ParseExact(month.Substring(0, 3), "MMM", CultureInfo.InvariantCulture).Month, i);
        var res = await GetLeavesAsync(i, month, year);

        ITEM.Date = dateTime.Day.ToString();
        ITEM.Day = dateTime.DayOfWeek.ToString();
        ITEM.LeaveCount = res.Count;
        ITEM.Leaves = res;
        if (res.Count > 0)
            ITEM.HighlightColor = res.Count < 5 ? System.Drawing.Color.Yellow : System.Drawing.Color.Tomato;

        ItemList.Add(ITEM);
    }

    return ItemList;
}

型号

 public class CalendarItem
    {
        public Color HighlightColor { get; set; }
        public string Date { get; set; }
        public string Day { get; set; }
        public int LeaveCount { get; set; }
        public List<LeaveDetail> Leaves { get; set; }
    }

根据你这里的代码,实际上有几个问题:

1) ViewModel 中的 ListItems 属性 本身并未实现 INotifyPropertyChanged。

public class ViewAViewModel : BindableBase
{
    private ObservableCollection<CalendarItem> _listItems;
    public ObservableCollection<CalendarItem> ListItems
    {
        get => _listItems;
        set => SetProperty(ref _listItems, value);
    }
}

2) 您正在 ViewLeaves 方法中新建一个 ListItems,然后一次添加一个项目。这里的结果是,如果您在设置 ListItems 时遵循第一步,它会尝试更新 UI,然后每次添加项目时,它都会尝试更新 UI.

3) 您有两种优化方法:

  • 使用 James Montemagno 在他的 MvvmHelpers 库中的 ObservableRangeCollection。这将允许您在 ctor 中更新集合,然后简单地转储一个集合,如:
private async void ViewLeaves()
{
    ListItems.ReplaceRange(await FirebaseService.GetAll(_month, _year));
}
  • 简单地实现 属性,如我指出的第一期中所示,但将其更改为 IEnumerable<CalendarItem> 并简单地设置为:
private async void ViewLeaves()
{
    ListItems = await FirebaseService.GetAll(_month, _year);
}

请尝试按如下方式修改您的列表项:-

    private ObservableCollection<CalendarItem> _listItems = new ObservableCollection<CalendarItem>();
    public ObservableCollection<CalendarItem> ListItems
    {
        get => _listItems;
        set => SetProperty(ref _listItems, value);
    }