How can I ensure my ListView is refreshed in Xamarin? - xamarin

I received some help yesterday. I am still new to c# and using Xamarin Forms with Prism as the MvvM Framework.
I pull data from an API and want to display it in a ListView, the api works and returns data correctly. If I return the data as a List and bind the list, I have to manually update the binding in the XAML (while running the application) in order to view the data in the rows.
I thought I may need to change to an ObservableCollection, but I didn't have much luck with it.
How can I correct this?
I will try to updated the OP with a gif showing my problem.
Here is my model:
public class OpenWorkOrder
{
public int ID { get; set; }
public string WOID { get; set; }
public string AssetNumber { get; set; }
public string WorkRequested { get; set; }
public Nullable<bool> Active { get; set; }
}
Here is the ViewModel:
private List<OpenWorkOrder> _openWO;
public List<OpenWorkOrder> OpenOrders
{
get { return _openWO; }
set { SetProperty(ref _openWO, value); }
}
private string selectedWO;
public string SelectedWO { get => selectedWO; set => SetProperty(ref selectedWO, value); }
private string wOID;
public string WOID { get => wOID; set => SetProperty(ref wOID, value); }
private string iD;
public string ID { get => iD; set => SetProperty(ref iD, value); }
private string workRequested;
public string WorkRequested { get => workRequested; set => SetProperty(ref workRequested, value); }
public async Task<List<OpenWorkOrder>> OpenWO()
{
var client = new RestClient("apiurl/");
var request = new RestRequest("Maint/GetOpenWorkOrders", Method.GET);
IRestResponse<List<OpenWorkOrder>> response = await client.ExecuteAsync<List<OpenWorkOrder>>(request);
if (response.StatusCode.ToString() == "OK")
{
return response.Data;
}
else
{
return null;
}
public async void OnNavigatedTo(INavigationParameters parameters)
{
try { OpenOrders = await OpenWO();
Console.WriteLine("Await Called!");
}
catch (Exception ex)
{
await _dialogService.DisplayAlertAsync("Exception Handled", ex.ToString(), "OK");
}
}
private List<OpenWorkOrder> _openWO;
public List<OpenWorkOrder> OpenOrders
{
get { return _openWO; }
set { SetProperty(ref _openWO, value); }
}
public async Task<List<OpenWorkOrder>> OpenWO()
{
var client = new RestClient("apiurl/");
var request = new RestRequest("Maint/GetOpenWorkOrders", Method.GET);
IRestResponse<List<OpenWorkOrder>> response = await client.ExecuteAsync<List<OpenWorkOrder>>(request);
if (response.StatusCode.ToString() == "OK")
{
return response.Data;
}
else
{
return null;
}
public async void OnNavigatedTo(INavigationParameters parameters)
{
try { OpenOrders = await OpenWO();
Console.WriteLine("Await Called!");
}
catch (Exception ex)
{
await _dialogService.DisplayAlertAsync("Exception Handled", ex.ToString(), "OK");
}
}
Here is the XAML:
<StackLayout Orientation="Horizontal">
<ListView x:Name="Data" ItemsSource="{Binding OpenOrders}"
GroupDisplayBinding="{Binding WOID}"
SelectionMode="Single">
<ListView.Behaviors>
</ListView.Behaviors>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label Text="{Binding WorkRequested}" HorizontalOptions="Center"/>
<Label Text="{Binding WOID}"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
EDIT: Attached gif here

Related

Xamarin Forms CollectionView is empty

I have a Xamarin Forms CollectionView, contained within a RefreshView. The binding source is populated but its not showing anything in the CollectionView. I know the binding source is populated as I show a count in the toolbar. Can anyone spot why the list is empty?
Here is my Content Page with my RefreshView and CollectionView:
<ContentPage.ToolbarItems>
<ToolbarItem Text="Add" Command="{Binding AddDogCommand}" />
<ToolbarItem Text="{Binding Dogs.Count}"></ToolbarItem>
</ContentPage.ToolbarItems>
<RefreshView x:DataType="local:MyDogsViewModel" Command="{Binding LoadDogsCommand}" IsRefreshing="{Binding IsBusy, Mode=TwoWay}">
<CollectionView ItemsLayout="HorizontalList" ItemsSource="{Binding Dogs}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid WidthRequest="100">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Grid.Column="1"
Text="{Binding DogName}"
FontAttributes="Bold" TextColor="Red"/>
<Label Grid.Row="1"
Grid.Column="1"
Text="{Binding Nickname}"
FontAttributes="Italic" TextColor="Green"
VerticalOptions="End" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</RefreshView>
Here is my ViewModel
public class MyDogsViewModel : BaseViewModel
{
private DogModel _selectedItem;
private DogService dogService = new DogService();
private string _dogName;
private string _nickname;
public ObservableCollection<DogModel> Dogs { get; }
public Command LoadDogsCommand { get; }
public Command<DogModel> ItemTapped { get; }
public Command AddDogCommand { get; }
public Command SaveDogCommand { get; }
public string DogName
{
get => _dogName;
set => SetProperty(ref _dogName, value);
}
public string Nickname
{
get => _nickname;
set => SetProperty(ref _nickname, value);
}
public MyDogsViewModel()
{
Title = "My Dogs";
Dogs = new ObservableCollection<DogModel>();
LoadDogsCommand = new Command(async () => await ExecuteLoadDogsCommand());
ItemTapped = new Command<DogModel>(OnItemSelected);
AddDogCommand = new Command(OnAddDog);
SaveDogCommand = new Command(OnSaveDog);
}
async Task ExecuteLoadDogsCommand()
{
IsBusy = true;
try
{
Dogs.Clear();
var dogs = await dogService.GetDogsAsync();
foreach (var d in dogs)
{
Dogs.Add(d);
}
}
catch (Exception ex)
{
Debug.WriteLine("Exception: " + ex);
}
finally
{
IsBusy = false;
}
}
public void OnAppearing()
{
IsBusy = true;
}
private async void OnAddDog(object obj)
{
await Shell.Current.GoToAsync(nameof(AddDogPage));
}
private async void OnSaveDog(object obj)
{
AddDogModel model = new AddDogModel
{
DogName = DogName,
Nickname = Nickname
};
await dogService.AddDog(model);
await Shell.Current.GoToAsync("..");
}
async void OnItemSelected(DogModel dog)
{
if (dog == null)
return;
}
}
DogModel class
public class DogModel
{
public int Id { get; set; }
public string DogName { get; set; }
public string Nickname { get; set; }
}
keep your xaml the same and i will edit your ViewModel and take out the properties that is causing you the issue ;
public class MyDogsViewModel : BaseViewModel
{
private DogModel _selectedItem;
private DogService dogService = new DogService();
private string _dogName;
private string _nickname;
private ObservableCollection<DogModel> dogs;
public ObservableCollection<DogModel> Dogs
{
get{return dogs;}
set{dogs=value;}
}
public Command LoadDogsCommand { get; set; }
public Command<DogModel> ItemTapped { get; set;}
public Command AddDogCommand { get; set;}
public Command SaveDogCommand { get; set;}
public MyDogsViewModel()
{
Title = "My Dogs";
Dogs = new ObservableCollection<DogModel>();
LoadDogsCommand = new Command(async () => await ExecuteLoadDogsCommand());
ItemTapped = new Command<DogModel>(OnItemSelected);
AddDogCommand = new Command(OnAddDog);
SaveDogCommand = new Command<object>(OnSaveDog);
}
async Task ExecuteLoadDogsCommand()
{
IsBusy = true;
try
{
Dogs.Clear();
var dogs = await dogService.GetDogsAsync();
foreach (var d in dogs)
{
Dogs.Add(d);
}
}
catch (Exception ex)
{
Debug.WriteLine("Exception: " + ex);
}
finally
{
IsBusy = false;
}
}
public void OnAppearing()
{
IsBusy = true;
}
private async void OnAddDog(object obj)
{
await Shell.Current.GoToAsync(nameof(AddDogPage));
}
private async void OnSaveDog(object obj)
{
DogModel newdog = obj as DogModel;
await dogService.AddDog(newdog);
await Shell.Current.GoToAsync("..");
}
async void OnItemSelected(DogModel dog)
{
if (dog == null)
return;
}
}
dont forget to bind to the viewmodel. in the xaml.cs add this in the constuctor.
this.BindingContext = new MyDogsViewModel();

How to Binding Result from ViewModel in Xamarin

I have 1 question here: How to get data from ViewModel in Xamarin, however I still haven't solved the problem. I created a new post with some changes.
I have:
PageOne.xaml
<StackLayout>
<RefreshView x:DataType="locals:ViewCustomerViewModel" Command="{Binding LoadUserinfoCommand}" IsRefreshing="{Binding IsBusy, Mode=OneWay}">
<Label Text="{Binding Customer.Address}" />
</RefreshView>
</StackLayout>
PageOne.xaml.cs
ViewCustomerViewModel viewCustomerViewModel;
public Customer CustomerGet { get; set; }
public PageOne()
{
InitializeComponent();
BindingContext = viewCustomerViewModel = new ViewCustomerViewModel();
viewCustomerViewModel.OnAppearing();
}
Class Customer
public class Customer
{
public string Address{ get; set; }
........
}
ViewCustomerViewModel
public class ViewCustomerViewModel:BaseCustomerViewModel
{
ApiServiceUserinfo apiServiceUserinfo = new ApiServiceUserinfo();
public Command LoadUserinfoCommand { get; }
public ObservableCollection<Customer> CustomerInfos { get; set; }
public ViewCustomerViewModel()
{
LoadUserinfoCommand = new Command(async () => await ExecuteLoadUserinfoCommand());
CustomerInfos = new ObservableCollection<Customer>();
}
public void OnAppearing()
{
IsBusy = true;
}
async Task ExecuteLoadUserinfoCommand()
{
string userget = "1";
IsBusy = true;
try
{
CustomerInfos.Clear();
var customerList = await apiServiceUserinfo.GetCustomersInfo(userget);
CustomerInfos.Add(customerList);
}
catch (Exception)
{
throw;
}
finally
{
IsBusy = false;
}
}
}
And I got the result CustomerInfos.Add(customerList);
However <Label Text="{Binding Customer.Address}" /> does not get results
Please help me again clearly in the answer. Thank you.
Update
ViewCustomerViewModel
public class ViewCustomerViewModel:BaseCustomerViewModel
{
ApiServiceUserinfo apiServiceUserinfo = new ApiServiceUserinfo();
public Command LoadUserinfoCommand { get; set;}
public Customer CustomerGets { get; set;}--> update
public ViewCustomerViewModel()
{
LoadUserinfoCommand = new Command(async () => await ExecuteLoadUserinfoCommand());
//CustomerGets = new Customer();
}
public void OnAppearing()
{
IsBusy = true;
}
async Task ExecuteLoadUserinfoCommand()
{
string userget = "1";
IsBusy = true;
try
{
var customerList = await apiServiceUserinfo.GetCustomersInfo(userget);
CustomerGets = customerList;
}
catch (Exception)
{
throw;
}
finally
{
IsBusy = false;
}
}
}
PageOne.xaml
<StackLayout>
<RefreshView x:DataType="locals:ViewCustomerViewModel" Command="{Binding LoadUserinfoCommand}" IsRefreshing="{Binding IsBusy, Mode=OneWay}">
<Label Text="{Binding CustomerGets.Address}" />
</RefreshView>
</StackLayout>
We need to call the OnPropertyChanged method to notify the change in setter method of the property .
private Customer customerGets;
public Customer CustomerGets {
get { return customerGets; }
set {
customerGets = value;
NotifyPropertyChanged(); //the method is declared in BaseCustomerViewModel
}
}
Ensure that BaseCustomerViewModel has implemented INotifyPropertyChanged , something like that
public class BaseCustomerViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

Xamarin Forms MVVM iOS ListView doesn't show; SelectedItem has data

I followed this example https://medium.com/swlh/xamarin-forms-mvvm-how-to-work-with-sqlite-db-c-xaml-26fcae303edd
I put a breakpoint in my OnRouteSelected event handler, and e.SelectedItem has the selected object, even though the ListView doesn't display it.
Am I missing something glaring below?
Here is my code:
RoutesPage.xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<ContentPage.Content>
<ListView ItemsSource="{Binding Routes}" SelectedItem="{Binding SelectedRoute, Mode=TwoWay}" HasUnevenRows="False" SeparatorColor="Gray" ItemSelected="OnRouteSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<Label TextColor="Black" Text="{Binding ROName}"/>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
</ContentPage>
RoutesPage.xaml.cs
public partial class RoutesPage : ContentPage
{
public RoutesPage()
{
InitializeComponent();
var routeStore = new RouteStore(DependencyService.Get<ISQLiteDb>());
var pageService = new PageService();
ViewModel = new RoutesPageViewModel(routeStore, pageService);
}
protected override void OnAppearing()
{
base.OnAppearing();
ViewModel.LoadDataCommand.Execute(null);
}
void OnRouteSelected(object sender, SelectedItemChangedEventArgs e)
{
ViewModel.SelectRouteCommand.Execute(e.SelectedItem);
}
public RoutesPageViewModel ViewModel
{
get { return BindingContext as RoutesPageViewModel; }
set { BindingContext = value; }
}
}
RoutesPageViewModel.cs The LoadData() method gets the data and adds it to the Routes Collection successfully.
public class RoutesPageViewModel : BaseViewModel
{
private RouteViewModel _selectedRoute;
private IRouteStore _routeStore;
private IPageService _pageService;
private bool _isDataLoaded;
public ObservableCollection<RouteViewModel> Routes { get; private set; }
= new ObservableCollection<RouteViewModel>();
public RouteViewModel SelectedRoute
{
get { return _selectedRoute; }
set { SetValue(ref _selectedRoute, value); }
}
public ICommand LoadDataCommand { get; private set; }
public ICommand AddRouteCommand { get; private set; }
public ICommand SelectRouteCommand { get; private set; }
public ICommand DeleteRouteCommand { get; private set; }
public ICommand CallRouteCommand { get; private set; }
public RoutesPageViewModel(IRouteStore routeStore, IPageService pageService)
{
_routeStore = routeStore;
_pageService = pageService;
LoadDataCommand = new Command(async () => await LoadData());
AddRouteCommand = new Command(async () => await AddRoute());
SelectRouteCommand = new Command<RouteViewModel>(async c => await SelectRoute(c));
}
private async Task LoadData()
{
if (_isDataLoaded)
return;
_isDataLoaded = true;
var routes = await _routeStore.GetRoutesAsync();
foreach (var route in routes)
Routes.Add(new RouteViewModel(route));
}
private async Task AddRoute()
{
// await _pageService.PushAsync(new RoutesDetailPage(new RouteViewModel()));
}
private async Task SelectRoute(RouteViewModel route)
{
if (route == null)
return;
SelectedRoute = null;
// await _pageService.PushAsync(new RoutesDetailPage(route));
}
}
The property in the viewmodels are being set like this:
private string _roName;
public string ROName
{
get { return _roName; }
set
{
SetValue(ref _roName, value);
OnPropertyChanged(nameof(ROName));
}
}
The constructor:
public RouteViewModel(Route route)
{
//other properties
ROName = route.ROName;
}

Xamarin button not being enabled

A User register page has a Save toolbar button. It is always disabled. The CanExecute method is not being called when a parameter is changed on screen. The Save button should be enabled by the CanExecute method when the user name and password are non blank and the PW and confirmpassword fields match. The CanExecute method is not being called when a change is made to any of the three fields.
Why isn't CanExecute method being called for the registerButton when something is entered into any of the three fields (username, PW, and ConfirmPassword ) The OnPropertyChanged method is being called for any change in these three fields, but apparently the external code is not detecting that a change has been made. Is this some kind of scope issue?
The entire project is available if necessary.
Jim Durbin
Here is the xaml code
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class=*"ButtonTest.RegisterPage"*>
<ContentPage.ToolbarItems>
**<ToolbarItem x:Name="registerButton"
Text="Save"
Command="{Binding RegisterCommand}"
CommandParameter="{Binding Password}"/>**
</ContentPage.ToolbarItems>
<ContentPage.Content>
<ScrollView Orientation="Vertical">
<StackLayout x:Name="containerStackLayout"
VerticalOptions="FillAndExpand"
Margin="20">
<Label Text="Registration"
FontSize="Large"
HorizontalOptions="Center"
FontAttributes="Bold"></Label>
<Entry x:Name="UserName"
Placeholder="User Name"
Text="{Binding UserName, Mode=TwoWay}"
Keyboard="Text"/>
<Entry x:Name="PasswordEntry"
Placeholder="Password"
Text="{Binding PW, Mode=TwoWay}"
IsPassword="True"/>
<Entry x:Name="confirmPasswwordEntry"
Placeholder="Confirm Password"
Text="{Binding ConfirmPassword, Mode=TwoWay}"
IsPassword="True"/>
<Entry x:Name="Email"
Placeholder="Email"
Text="{Binding Email, Mode=TwoWay}"
Keyboard="Email"/>
</StackLayout>
</ScrollView>
</ContentPage.Content>
</ContentPage>
viewModel code
using ButtonTest.Model;
using System.ComponentModel;
using ButtonTest.ViewModel.Commands;
namespace ButtonTest.ViewModel
{
public class RegisterPageVM : INotifyPropertyChanged
{
public RegisterCommand RegisterCommand { get; set; }
private Password user;
public Password User
{
get { return user; }
set
{
user = value;
OnPropertyChanged("User");
}
}
private string username;
public string UserName
{
get { return username; }
set
{
username = value;
User = new Password()
{
UserName = this.UserName,
PW = this.PW,
ConfirmPassword = this.ConfirmPassword
};
OnPropertyChanged("UserName");
}
}
private string pw;
public string PW
{
get { return pw; }
set
{
pw = value;
User = new Password()
{
UserName = this.UserName,
PW = this.PW,
ConfirmPassword = this.ConfirmPassword
};
OnPropertyChanged("PW");
}
}
private string confirmpassword;
public string ConfirmPassword
{
get { return confirmpassword; }
set
{
confirmpassword = value;
User = new Password()
{
UserName = this.UserName,
PW = this.PW,
ConfirmPassword = this.ConfirmPassword
};
OnPropertyChanged("ConfirmPassword");
}
}
public RegisterPageVM()
{
RegisterCommand = new RegisterCommand(this);
//User = new Password();
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public void Register(Password user)
{
Password.Register(user);
}
}
}
Here is the command code
using System;
using System.Windows.Input;
using ButtonTest.Model;
namespace ButtonTest.ViewModel.Commands
{
public class RegisterCommand : ICommand
{
private RegisterPageVM viewModel;
public RegisterCommand(RegisterPageVM viewModel)
{
this.viewModel = viewModel;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
Password user = (Password)parameter;
if (user != null)
{
if (user.PW == user.ConfirmPassword)
{
if (string.IsNullOrEmpty(user.UserName) || string.IsNullOrEmpty(user.PW))
return false;
return true;
}
return false;
}
return false;
}
public void Execute(object parameter)
{
Password user = (Password)parameter;
viewModel.Register(user);
}
}
}
here is the Password.cs code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Numerics;
using System.Linq;
using System.Threading.Tasks;
namespace ButtonTest.Model
{
public class Password : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private string username;
public string UserName
{
get { return username; }
set
{
username = value;
OnPropertyChanged("UserName");
}
}
private string pw;
public string PW
{
get { return pw; }
set
{
pw = value;
OnPropertyChanged("PW");
}
}
private string confirmPassword;
public string ConfirmPassword
{
get { return confirmPassword; }
set
{
confirmPassword = value;
OnPropertyChanged("ConfirmPassword");
}
}
private string email;
public string Email
{
get { return email; }
set { email = value; }
}
public static async void Insert(Password password)
{
await App.client.GetTable<Password>().InsertAsync(password);
//await App.client.SyncContext.PushAsync();
}
public static async Task<bool> Delete(Password password)
{
try
{
await App.passwordsTable.DeleteAsync(password);
//await App.client.SyncContext.PushAsync();
return true;
}
catch (Exception)
{
return false;
}
}
public static async void Register(Password user)
{
await App.client.GetTable<Password>().InsertAsync(user);
}
public static async Task<bool> Login(string username, string password)
{
bool isEmailEmpty = string.IsNullOrEmpty(username);
bool isPasswordEmpty = string.IsNullOrEmpty(password);
if (isEmailEmpty || isPasswordEmpty)
{
return false;
}
else
{
var user = (await App.client.GetTable<Password>().Where(u => u.UserName == username).ToListAsync()).FirstOrDefault();
if (user != null)
{
App.user = user;
if (user.pw == password)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
}
}
}
This problem is solved. The CommandParameter binding for the RegisterCommand needed to be set to the User property in the VM. The CanExecute method is now being called for each change in the UserName, PW, and ConfirmPassword fields.
It was solved by E.Z. Hart from the github support group. Many thanks for the solution.

Binding in Xamarin.Forms does not work after web API request

I am trying to make simple app which will provide features to read/write data to database trough an Web API.
I have view model which is bind to view, but it is not working properly after web api get request, even that call was successfully done. I've tried to check value with display alert, value is correct, but it is not presented in view part, exactly in one label. Here is my code:
<?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="SOSEUApp.Pages.NotePage"
Title="Dnevnik">
<ContentPage.ToolbarItems>
<ToolbarItem Text="GET" Clicked="ToolbarItem_Clicked"></ToolbarItem>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout Orientation="Vertical">
<ActivityIndicator IsRunning="{Binding IsBusy}" IsVisible="{Binding IsBusy}"></ActivityIndicator>
<StackLayout Orientation="Vertical">
<Label Text="{Binding Date,StringFormat='Date: {0}'}"></Label>
</StackLayout>
<StackLayout>
</StackLayout>
</StackLayout>
</ContentPage.Content>
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class NotePage : ContentPage
{
NoteViewModel nvm = new NoteViewModel();
public NotePage()
{
InitializeComponent();
BindingContext = nvm;
}
private async void ToolbarItem_Clicked(object sender, EventArgs e)
{
nvm.IsBusy = true;
nvm.Notes = await App.NotesWebApiService.GetAll(nvm.CurrentActiveNote.Route);
nvm.GetLastNote();
nvm.IsBusy = false;
await DisplayAlert("Info", nvm.Date.ToString(), "Close");
}
}
public class NoteViewModel : BaseViewModel
{
IList<Note> notes = new List<Note>();
public IList<Note> Notes
{
get { return notes; }
set { SetProperty(ref notes, value); }
}
private Note currentActiveNote = new Note();
public Note CurrentActiveNote { get { return currentActiveNote; } }
public string Date { get { return currentActiveNote.Date.ToString("dd.MM.yyyy"); } }
public string OrderedNumber
{
get { return currentActiveNote.OrderNumber.ToString(); }
set
{
string v = currentActiveNote.OrderNumber.ToString();
SetProperty(ref v, value);
currentActiveNote.OrderNumber = Convert.ToInt16(v);
}
}
public string Description
{
get { return currentActiveNote.Description; }
set
{
string v = currentActiveNote.Description;
SetProperty(ref v, value);
currentActiveNote.Description = v;
}
}
public void GetLastNote()
{
notes.OrderBy(a => a.Date);
currentActiveNote = notes.Last();
}
}
public class BaseViewModel : DataModel, INotifyPropertyChanged
{
bool isBusy = false;
public bool IsBusy
{
get { return isBusy; }
set { SetProperty(ref isBusy, value); }
}
string title = string.Empty;
public string Title
{
get { return title; }
set { SetProperty(ref title, value); }
}
protected bool SetProperty<T>(ref T backingStore, T value,
[CallerMemberName]string propertyName = "",
Action onChanged = null)
{
if (EqualityComparer<T>.Default.Equals(backingStore, value))
return false;
backingStore = value;
onChanged?.Invoke();
OnPropertyChanged(propertyName);
return true;
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var changed = PropertyChanged;
if (changed == null)
return;
changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
Thank you in advance!
just called SetProperty method and passed desired values there. It works
Said as Jason, you need to fire a PropertyChanged event when Date changes.Here is official document for reference.
Generally, usually writed in Set methods.As follow:
private string propertyname;
public string PropertyName
{
set { SetProperty(ref propertyname, value); }
get { return propertyname; }
}
Or write as follow:
public string PropertyName
{
set
{
if (propertyname!= value)
{
propertyname= value;
OnPropertyChanged("PropertyName");
}
}
get
{
return propertyname;
}
}
bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Object.Equals(storage, value))
return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
When data of model change , this will be invoked automatically.

Resources