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

时间:2019-10-09 06:28:43

标签: xamarin mvvm xamarin.forms prism

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

在下面的代码中,我试图获得以下结果-

  • 将从Firebase收到的响应序列化,然后根据响应创建自定义日历。
  • 要创建日历,我使用的模型将包含要在视图中显示的所有必要绑定。例如颜色,标题,计数等。

我正在使用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; }
    }

2 个答案:

答案 0 :(得分:1)

根据此处提供的代码,实际上存在两个问题:

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);
}

答案 1 :(得分:1)

请尝试如下修改您的ListItem:-

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