Sasha
Sasha

Reputation: 1724

ListView.ItemTemplate not being set and events not firing

I'm working on a Xamarin project in order to learn how it works, but i've ran into a problem I can't seem to work out.

I have a listview itemplate stored inside the listview tag in my XAML, which defines a label and the text for that label is a binding set from the data source, although when my items are loaded in through the itemsource it's using my overridden tostring rather than my binding, which causes a problem. My itemtapped event handlers are also not working and don't seem to be firing. I am using VS for mac.

Here's my XAML for the form

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="BrainStorageApp.MainPage"
             Title="View Notes">
  <ListView ItemsSource="{Binding Items}"
            x:Name="MainListView"
            HasUnevenRows="true"
            IsGroupingEnabled="true"
            IsPullToRefreshEnabled="true"
            IsEnabled="true"
            CachingStrategy="RecycleElement"
            IsRefreshing="{Binding IsBusy, Mode=OneWay}"
            RefreshCommand="{Binding RefreshDataCommand}">
    <ListView.Header>
      <StackLayout Padding="40" 
                   Orientation="Horizontal"
                   HorizontalOptions="FillAndExpand"
                   BackgroundColor="{StaticResource Primary}}">
        <Label Text="Your Notes"
               HorizontalTextAlignment="Center"
               HorizontalOptions="FillAndExpand"
               TextColor="White"
               FontAttributes="Bold"/>
      </StackLayout>
    </ListView.Header>
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <Label Text="{Binding title}" FontSize="14" />
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</ContentPage>

Hope i'm not just being stupid and missing something, as my XAML seems to build fine and my itemsource seems to work fine. If you need to see my code behind just comment and i'll edit to provide.

EDIT: Unsure whether it makes any difference, but this page is located in a tabbing page.

EDIT 2: Here's the code for my main xaml.cs file, as requested.

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace BrainStorageApp
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class MainPage : ContentPage
    {

        private BrainstorageApiClass BrainstorageClass;
        private UserClass User;

        public MainPage(string username)
        {
            InitializeComponent();
            BrainstorageClass = new BrainstorageApiClass();
            User = new UserClass();
            User.Username = username;
            BindingContext = new ListViewPageViewModel(BrainstorageClass.LoadNotes(User.Username));
        }

        void Handle_ItemTapped(object sender, Xamarin.Forms.ItemTappedEventArgs e)
        {
            Console.WriteLine(sender.ToString());
        }
    }



    class ListViewPageViewModel : INotifyPropertyChanged
    {
        public ObservableCollection<NoteItem> Items { get; }

        public ListViewPageViewModel(List<NoteItem> list)
        {
            Items = new ObservableCollection<NoteItem>(list);
            RefreshDataCommand = new Command(
                async () => await RefreshData());
        }

        public ICommand RefreshDataCommand { get; }

        async Task RefreshData()
        {
            IsBusy = true;
            //Load Data Here
            await Task.Delay(2000);

            IsBusy = false;
        }

        bool busy;
        public bool IsBusy
        {
            get { return busy; }
            set
            {
                busy = value;
                OnPropertyChanged();
                ((Command)RefreshDataCommand).ChangeCanExecute();
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;
        void OnPropertyChanged([CallerMemberName]string propertyName = "") =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

EDIT 3:

NoteItem

namespace BrainStorageApp
{
    public class NoteItem
    {
        public int id;
        public string title;
        public string content;
        public DateTime createdat;
        public DateTime updatedat;

        public NoteItem(JToken Token)
        {
            id = int.Parse(Token["id"].Value<string>());
            title = Token["Note_Title"].Value<string>();
            content = Token["Note_Content"].Value<string>();
            createdat = DateTime.Parse(Token["created_at"].Value<string>());
            updatedat = DateTime.Parse(Token["updated_at"].Value<string>());
        }

        public override string ToString()
        {
            return title;
        }
    }
}

Upvotes: 1

Views: 1463

Answers (1)

Sven-Michael St&#252;be
Sven-Michael St&#252;be

Reputation: 14750

If you want to bind something, it has to be a property. title is no property.

public class NoteItem
{
    public int id {get;}
    public string title {get;}
    public string content {get;}
    public DateTime createdat {get;}
    public DateTime updatedat {get;}
}

Note

Usually in C#, Properties start with an upper case letter.

public class NoteItem
{
    public int Id {get;}
    public string Title {get;}
    public string Content {get;}
    public DateTime CreateDate {get;}
    public DateTime UpdateDate {get;}
}

But don't forget to update your binding then.

<Label Text="{Binding Title}" FontSize="14" />

Upvotes: 2

Related Questions