Home > Software design >  Can't see anything on the Xamarin ListView (DataBinding - MVVM)
Can't see anything on the Xamarin ListView (DataBinding - MVVM)

Time:02-16

I tried to use some DataBindings on the listview but nothing is listed.

Model.cs

public class Post
{
    // Columns inside of the Database table

    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }

    [MaxLength(250)]
    public string Experience { get; set; }
}

MainViewModel.cs

private ObservableCollection<Post> _postList;
public  ObservableCollection<Post> PostList
{
    get { return _postList; }
    set { SetProperty(ref _postList, value); }
}

public void ReadDataBase()
{
    using (SQLiteConnection conn = new SQLiteConnection(App.DatabaseLocation))
    {
        conn.CreateTable<Post>();
        var postList = conn.Table<Post>().ToList();
        PostList = new ObservableCollection<Post>(postList);
    }
}

HistoryPage.xaml

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:viewModel ="clr-namespace:TravelRecordApp.ViewModel"
             x:Class="TravelRecordApp.View.HistoryPage">

    <ContentPage.BindingContext>
        <viewModel:MainViewModel/>
    </ContentPage.BindingContext>
    <ListView x:Name="postListView" ItemsSource="{Binding PostList}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <TextCell Text="{Binding Experience}"/>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</ContentPage>

HistoryPage.xaml.cs

protected override void OnAppearing()
{
    base.OnAppearing();
    MainViewModel mv = new MainViewModel();
    mv.ReadDataBase();
}

Notes:

After debugging I confirmed that whenever I go to the HistoryPage, the PostList is updated with the new data. So SQL Data reading and page navigation is working fine. I just can not see the contents from the ListView.

I tried also using just List<Post> before ObservableCollection, the result is the same.

CodePudding user response:

the problem in your code is that your xaml is binding to an instance that is different then the one your calling ReadDataBase() function from. try please my solution please:

private ObservableCollection<Post> _postList;
public  ObservableCollection<Post> PostList
{
    get { return _postList; }
    set { _postList =value; }
}

remove the <ContentPage.BindingContext> from xaml;

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:viewModel ="clr-namespace:TravelRecordApp.ViewModel"
             x:Class="TravelRecordApp.View.HistoryPage">
  <ContentPage.Content>
    <ListView x:Name="postListView" ItemsSource="{Binding PostList}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <TextCell Text="{Binding Experience}"/>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
  </ContentPage.Content>
</ContentPage>

in the code behind

private MainViewModel viewModel;
public HistoryPage() // constructor 
        {
            InitializeComponent();
            viewModel = new MainViewModel();
            this.BindingContext = viewModel;
        }
protected override void OnAppearing()
{
    base.OnAppearing();
    viewModel.ReadDataBase();
}

CodePudding user response:

The root cause is that you only need add post to PostList after var postList = conn.Table().ToList();This works well on my side.

Below is the ViewModel code:

    public class HistoryPageViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private ObservableCollection<Post> _postList;
    public ObservableCollection<Post> PostList
    {
        get => _postList;

        set { 
            _postList = value;
        }
    }
    public HistoryPageViewModel()
    {
        PostList = new ObservableCollection<Post>();
    }

    public void ReadDataBase()
    {
        using (SQLiteConnection conn = new SQLiteConnection(App.DatabaseLocation))
        {
            conn.CreateTable<Post>();
            var postList = conn.Table<Post>().ToList();

            foreach (var post in postList)
            {
                PostList.Add(post); 
            }
        }
    }
}

Below is the code behind:

 public partial class HistoryPage : ContentPage
{
    HistoryPageViewModel vm;
    public HistoryPage()
    {
        InitializeComponent();

        vm = new HistoryPageViewModel();
        this.BindingContext = vm;
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();

        vm.ReadDataBase();
    }
    private void Button_Clicked(object sender, EventArgs e)
    {
        Navigation.PushAsync(new NewTravelPage());
    }
}

Below is the code in xaml:

    <StackLayout HorizontalOptions="Center" VerticalOptions="FillAndExpand" Padding="10">
    <ListView  ItemsSource="{Binding PostList}" >
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <Label Text="{Binding Experience}" TextColor="Black" FontSize="Large"></Label>
                </ViewCell>                       
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

    <Button Clicked="Button_Clicked"></Button>
</StackLayout>
  • Related