0

I want to make a simple login UI in xaml using Xamarin. I create a username and password field with Entry in the MainPage and then I try to bind them to my LoginViewModel where I can access my connexion method.

When I define the Binding context in the Mainpage codebehind the application simply shutdown and I dont understand why, what am I doing wrong ?

MainPage.xaml

<?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:local="clr-namespace:suivAAndroid" x:Class="suivAAndroid.MainPage"> <StackLayout VerticalOptions="CenterAndExpand"> <Image></Image> <Label Text="Login" StyleId="lbl_login"></Label> <Entry StyleId="ent_login" Text="{Binding Username}"></Entry> <Label Text="Mot de passe" StyleId="ent_mdp"></Label> <Entry StyleId="ent_mdp" Text="{Binding Password}"></Entry> <Button Clicked="connexion_click" Text="Connexion"></Button> </StackLayout> </ContentPage> 

MainPage.xaml.cs

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Xamarin.Forms; using Xamarin.Forms.Xaml; namespace suivAAndroid { public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); BindingContext = new LoginViewModel(); // Here is where it does not work. If the line is commented out, then the application launch without stopping but because there is no binding context I cant get the user inputs. } private void connexion_click(object sender, EventArgs e) { LoginViewModel connexionBtn = new LoginViewModel(); Device.BeginInvokeOnMainThread(async () => { await connexionBtn.Connexion(); }); } } } 

LoginViewModel.cs

using suivAAndroid.Models; using suivAAndroid.Views; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace suivAAndroid { public class LoginViewModel { #region propriétés public string Username { get { return Username; } set { Username = value; } } public string Password { get { return Password; } set { Password = value; } } #endregion #region constructor public LoginViewModel() { } #endregion #region methodes public void CreerListeVisiteurDur(List<Visiteur> uneListe) { Visiteur unVisiteur = new Visiteur("Clooney", "George", "cgeorge", "azerty", "rue du port", "59", "lille", new DateTime(2015 / 07 / 13)); uneListe.Add(unVisiteur); } public async Task Connexion() { List<Visiteur> uneListe = new List<Visiteur>(); CreerListeVisiteurDur(uneListe); if (!string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password)) { foreach (Visiteur unVisiteur in uneListe) { string login = unVisiteur.login; string pass = unVisiteur.mdp; if (login == Username && pass == Password) { App.Current.MainPage = new CreerVisite(); } } } } #endregion } } 

2 Answers 2

2

Your ViewModel properties have infinite loops:

 public string Username { get { return Username; } set { Username = value; } } 

calling Username = value will call set on Username which in turn calls Username = value again.

Also, in order for your ViewModel to be bindable, you must implement INotifyPropertyChanged.

If you want a framework that is easy to use to help you do this, I would suggest Mvvm Light.

Here's an example of what your ViewModel should look like:

public class MyViewModel : INotifyPropertyChanged { public event EventHandler<PropertyChangedEventArgs> OnPropertyChanged; private string _username; public string Username { get { return _username; } set { _username = value; PropertyChanged?.Invoke(new PropertyChangedEventArgs("Username"); } } .... } 
Sign up to request clarification or add additional context in comments.

2 Comments

PropertyChanged?.Invoke(new PropertyChangedEventArgs("Username"); what does this line do ?
The PropertyChanged is what Xamarin.Forms looks for in order to update the view. When you set the BindingContext, Xamarin.Forms will check if it implements INotifyPropertyChanged, and if it does, it will attach an EventHandler. So when you invoke it, it updates the view wherever you having a Binding to that property.
1
  1. in connexion_click you are creating a new copy of your VM that has no relation to the prior copy you created for your BindingContext.

    public partial class MainPage : ContentPage { private LoginViewModel vm;

     public MainPage() { InitializeComponent(); vm = new LoginViewModel(); BindingContext = vm; } private void connexion_click(object sender, EventArgs e) { Device.BeginInvokeOnMainThread(async () => { await vm.Connexion(); }); } } 
  2. your VM should implement INotifyPropertyChanged

  3. your VM has a recursive getter

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.