Пользовательская привязка ListView не работает в Xamarin.Forms - PullRequest
0 голосов
/ 09 октября 2019

Я пытаюсь связать ответ с пользовательским ListView в Xamarin.Forms, но ListView остается пустым, даже когда ObservableCollection содержит результаты. Пожалуйста, укажите мою ошибку в коде ниже.

В приведенном ниже коде я пытаюсь добиться следующего результата -

  • Ответ, полученный от 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 ]

1 голос
/ 09 октября 2019

Пожалуйста, попробуйте изменить свои ListItems следующим образом: -

    private ObservableCollection<CalendarItem> _listItems = new ObservableCollection<CalendarItem>();
    public ObservableCollection<CalendarItem> ListItems
    {
        get => _listItems;
        set => SetProperty(ref _listItems, value);
    }
1 голос
/ 09 октября 2019

Исходя из имеющегося здесь кода, на самом деле существует пара проблем:

1) Ваше свойство ListItems в ViewModel само по себе не реализует INotifyPropertyChanged.

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

2) Вы обновляете ListItems в методе ViewLeaves, а затем добавляете каждый элемент по одному. В результате получается, что если вы выполнили первый шаг при установке ListItems, он попытался бы обновить пользовательский интерфейс, а затем каждый раз, когда вы добавляете элемент, он будет пытаться обновить пользовательский интерфейс.

3) У вас есть дваВарианты оптимизации:

  • Используйте ObservableRangeCollection, который есть у Джеймса Монтемагно в его библиотеке MvvmHelpers. Это позволит вам обновить коллекцию в ctor, а затем просто вывести коллекцию следующим образом:
private async void ViewLeaves()
{
    ListItems.ReplaceRange(await FirebaseService.GetAll(_month, _year));
}
  • Просто реализуйте свойство, как показано в первом выпуске, который я указал, ноизмените его на IEnumerable<CalendarItem> и просто установите его следующим образом:
private async void ViewLeaves()
{
    ListItems = await FirebaseService.GetAll(_month, _year);
}
...