Lasse Edsvik
Lasse Edsvik

Reputation: 9298

Refresh data in TabbedPage using MVVM

I have a TabbedPage where I add entries and in the other tabs I list data. How can I refresh the data after I've added an entry to database using MVVM?

MainPage:

<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:myMood.Views"
             x:Class="myMood.Views.MainPage"
            BackgroundImage="logo.png">

    <local:Register></local:Register>
    <local:Entries></local:Entries>
    <local:Statistics></local:Statistics>
    <local:Settings></local:Settings>
    <local:About></local:About>
</TabbedPage>

Entries:

<?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="myMood.Views.Entries"
             Icon="ic_view_headline_white_24dp.png"
             xmlns:viewModels="clr-namespace:myMood.ViewModels">
    <ContentPage.BindingContext>
        <viewModels:EntriesViewModel />
    </ContentPage.BindingContext>

    <ListView ItemsSource="{Binding MoodEntries}" 
              HasUnevenRows="True"
              Margin="20">
        <ListView.Header>
            <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="30*" />
                <ColumnDefinition Width="50*" />
                <ColumnDefinition Width="50*" />
                <ColumnDefinition Width="50*" />
            </Grid.ColumnDefinitions>

                <Image Source="ic_date_range_black_24dp.png" Grid.Column="0" Grid.Row="0" HorizontalOptions="Center"></Image>
                <Image Source="ic_local_hotel_black_24dp.png" Grid.Column="1" Grid.Row="0" HorizontalOptions="Center"></Image>
                <Image Source="ic_directions_run_black_24dp.png" Grid.Column="2" Grid.Row="0" HorizontalOptions="Center"></Image>
                <Image Source="ic_done_all_black_24dp.png" Grid.Column="3" Grid.Row="0" HorizontalOptions="Center"></Image>
            </Grid>
        </ListView.Header>
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="30*" />
                            <ColumnDefinition Width="50*" />
                            <ColumnDefinition Width="50*" />
                            <ColumnDefinition Width="50*" />
                        </Grid.ColumnDefinitions>
                        <Label Text="{Binding EntryDate, StringFormat='{0:d/M}'}" Grid.Column="0" Grid.Row="0" HorizontalOptions="Center"></Label>
                        <Label Text="{Binding Sleep, StringFormat='{0:0.0}'}" Grid.Column="1" Grid.Row="0" HorizontalOptions="Center"></Label>
                        <Label Text="{Binding Stress, StringFormat='{0:0.0}'}" Grid.Column="2" Grid.Row="0" HorizontalOptions="Center"></Label>
                        <Label Text="{Binding AchivedGoals, StringFormat='{0:0.0}'}" Grid.Column="3" Grid.Row="0" HorizontalOptions="Center"></Label>
                        <Label Text="{Binding Comment, StringFormat='{0:0.0}'}" Grid.Column="0" Grid.ColumnSpan="4" Grid.Row="1"></Label>
                    </Grid>                    
                </ViewCell>                
            </DataTemplate>            
        </ListView.ItemTemplate>
    </ListView>    
</ContentPage>

ViewModel:

using myMood.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace myMood.ViewModels
{
    public class EntriesViewModel
    {
        public List<MoodEntry> MoodEntries { get; set; }

        public EntriesViewModel()
        {
            MoodEntries = App.MoodDatabase.GetMoodEntries();
        }
    }
}

Register Viewmodel:

namespace myMood.ViewModels
{
    public class RegisterViewModel : INotifyPropertyChanged
    {
        public MoodEntry MoodEntry { get; set; }
        public DateTime LowerLimitDate { get; set; }
        public DateTime HighLimitDate { get; set; }

        public Command SaveEntry
        {
            get
            {
                return new Command(() =>
                    App.MoodDatabase.SaveMoodEntry(MoodEntry));
            }
        }

        public RegisterViewModel()
        {
            MoodEntry = App.MoodDatabase.GetMoodEntry(DateTime.Today);
            if (MoodEntry == null)
                MoodEntry = new MoodEntry();

            LowerLimitDate = new DateTime(2018, 1, 1);
            HighLimitDate = DateTime.Today;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Upvotes: 0

Views: 1371

Answers (1)

Sebastian Jensen
Sebastian Jensen

Reputation: 154

You need to implement the INotifyPropertyChanged Interface in your viewmodel. Because Currently the viewmodel sends no signal to the UI that the data has changed.

So your viewmodel should look like this:

public class EntriesViewModel : INotifyPropertyChanged
{
    private List<MoodEntry> _moodEntries;
    public List<MoodEntry> MoodEntries
    {
        get { return _moodEntries; }
        set { _moodEntries = value; OnPropertyChanged(); }
    }

    public EntriesViewModel()
    {
        MoodEntries = App.MoodDatabase.GetMoodEntries();
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Upvotes: 2

Related Questions