Xamarin Forms ListView не показывает содержимое

Я рендер ListView

<StackLayout>
<Label Text = "Test"/> //This Label is getting rendered
<ListView  ItemsSource = "{Binding MusicList,Mode=TwoWay}"
                HasUnevenRows = "True"
                IsPullToRefreshEnabled = "True"
                CachingStrategy = "RecycleElement"
                SeparatorColor = "DarkGray">
      <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <Label Text = "{Binding Name}" TextColor = "Black"/>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</StackLayout>

Чей ItemsSource привязан к ObservableCollection<Music>, который доступен в ViewModel. Вот как я привязываю ViewModel.

public MainPage()
{
    BindingContext = new MainViewModel();
    InitializeComponent();
}

Это мой ViewModel, и здесь я вызываю методы API для получения данных.

    private ObservableCollection<Music> _MusicList=new ObservableCollection<Music>();
    public ObservableCollection<Music> MusicList
    {
        get { return _MusicList; }
        set
        {
            if (_MusicList != value)
            {
                _MusicList = value;
                OnPropertyChanged("_MusicList");
            }
        }
    }
    public MainViewModel()
    {
        api = new ApiHelper();
        GetSongs();
    }

    public async void GetSongs()
    {
        _MusicList = new ObservableCollection<Music>(await api.GetMusicListAsync());
    }

Данные поступают в ObservableCollection<Music>Xamarin Forms ListView не показывает содержимое

ОБНОВИТЬ

Просто для тестирования я попытался привязать простой строковый список ListStrings = new List<string> {"A","B","C","D","E","F" };, но он также не появился.

ОБНОВИТЬ Теперь я переопределил метод onAppearing, инициализировал свой список и установил для него ListView ItemsSource. и он работает сейчас .. но не знаю, почему он не работает с привязкой.

Замените этот MusicList = new ObservableCollection<Music>(await api.GetMusicListAsync()); на этот _MusicList = new ObservableCollection<Music>(await api.GetMusicListAsync());

MShah 10.08.2018 12:45

У вас есть свойство Name в вашем классе Music?

Dennis Schröer 10.08.2018 14:29
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
1 834
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Есть пара вещей, которые могут вызвать проблемы.

  1. ItemsSource = "{Binding MusicList,Mode=TwoWay}" есть ли веская причина сделать его двухсторонним? Если нет, не делай этого.
  2. Установите BindingContext после InitializeComponent();
  3. Не создавайте новый ObservableCollection при получении данных. Создавая новую коллекцию, вы теряете привязку данных. Вместо этого измените его так:

    public async void GetSongs()
    {
        var result = await api.GetMusicListAsync();
    
        foreach (var r in result)
            _MusicList.Add(r);
    }
    

извините, но ничего не помогло ... я переопределил метод onAppearing, тогда он показал список ... пока не понимаю проблему: /

Sameer Kamran 13.08.2018 08:30

Пожалуйста, обновите вопрос, указав, что вы пробовали до сих пор

Gerald Versluis 13.08.2018 08:45

Я думаю, вы совершили ошибку, подняв недвижимость после изменения:

private ObservableCollection<Music> _MusicList=new 
ObservableCollection<Music>();
public ObservableCollection<Music> MusicList
{
    get { return _MusicList; }
    set
    {

            _MusicList = value;
            OnPropertyChanged("MusicList");  //You should raise property change on your Binding variable.

    }
}

Как сказал @Gerald, следуйте его совету, и я добавляю, чтобы дать вам представление о решении третьей проблемы, которую он упомянул.

Если вы создаете свою Observable Collection каждый раз, когда получаете данные, вы теряете привязку данных. Если вы используете метод foreach, который будет вызывать событие изменения коллекции несколько раз, если у вас большой список, это может быть проблемой для вас.

Следующая расширенная коллекция поддерживает различные типы коллекции и имеет свойство Сбросить наблюдаемую коллекцию.

В конструкторе модели представления вы можете инициализировать свою коллекцию один раз, например:

public MusicPageViewModel()
{
     MusicsData=new ExtendedCollection<Music>();
}

Затем всякий раз, когда вы будете получать данные из своего API, вы будете делать что-то вроде:

public GetMusicsData()
{
     MusicsData.Reset(YourApi.GetMusics());
}

Надеюсь, это поможет вам реализовать вашу коллекцию Observable. Это расширенная коллекция Observable, которую вы можете использовать и расширять, если вам нужно:

public class ExtendedCollection<T> : ObservableCollection<T>
{
    public ExtendedCollection()
        : base()
    {
    }
    public ExtendedCollection(IEnumerable<T> collection)
        : base(collection)
    {
    }

    public ExtendedCollection(List<T> list)
        : base(list)
    {
    }

    /// <summary>
    /// Reset the existings items and fills the new items provided.
    /// </summary>
    /// <param name = "range"></param>
    public void Reset(IEnumerable<T> range)
    {
        this.Items.Clear();

        if (range != null)
        {
            AddRange(range);
        }

    }

    /// <summary>
    /// Add all items in the range;
    /// </summary>
    /// <param name = "range"></param>
    public void AddRange(IEnumerable<T> range)
    {
        foreach (var item in range)
        {

            Items.Add(item);
        }

        //Raise the property change!
        this.OnPropertyChanged(new PropertyChangedEventArgs("Count"));
        this.OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
        this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }
}

извините, но ничего не помогло ... я переопределил метод onAppearing, тогда он показал список ... пока не понимаю проблему: /

Sameer Kamran 13.08.2018 08:29
Ответ принят как подходящий

Сегодня нашел решение.

    public MainPage()
    {
        InitializeComponent();
        BindingContext = this; //Added this 
    }

Просто добавил BindingContext = this; в конструктор. Я не знаю, что не так с Xamarin, думаю, это ошибка.

Я последовал за ответом @Gerald Versluis, и это сработало. Я создавал новый Observable при получении данных, и мне нужно было просто использовать метод add () из Observable. Кроме того, мне пришлось инициализировать Observable в конструкторе моей ViewModel.

jan4co 17.12.2018 17:20

Эта проблема была решена изменением способа объявления свойств в наблюдаемом объекте. Пример:

Это не удалось

public class MusicItem
{
     public string Name;
}

Это сработало успешно:

public class MusicItem
{
     public string Name {get; set;}
}

Привязка не может найти имя свойства в первом примере, но работает во втором.

Другие вопросы по теме