我想使用Xamarin在xaml中创建一个简单的登录UI。我在MainPage中使用Entry创建一个用户名和密码字段,然后我尝试将它们绑定到我的LoginViewModel,在那里我可以访问我的connexion方法。
当我在Mainpage代码后面定义Binding上下文时,应用程序只是关闭,我不明白为什么,我做错了什么?
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
}
}
答案 0 :(得分:2)
您的ViewModel属性具有无限循环:
$http.get('catalog/view/theme/default/template/confirm/fetch_product.php').then(function(response){ $scope.products = response.data.records; });
$scope.items = [];
var counter = 0;
$scope.loadMore = function($scope) {
var last = $scope.products.length;
for (var i = 0; i < 10; i++) {
if(counter >= last) { break; }
$scope.items.push($scope.products[counter]);
counter += 1;
}
};
$scope.loadMore();
致电 public string Username
{
get
{
return Username;
}
set
{
Username = value;
}
}
会致电Username = value
上的set
,Username
会再次致电Username = value
。
此外,为了使ViewModel可绑定,您必须实现INotifyPropertyChanged
。
如果你想要一个易于使用的框架来帮助你做到这一点,我建议Mvvm Light。
以下是ViewModel的示例:
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");
}
}
....
}
答案 1 :(得分:1)
在connexion_click中,您创建的VM副本与您为BindingContext创建的先前副本无关。
公共部分类MainPage:ContentPage { 私人LoginViewModel vm;
public MainPage()
{
InitializeComponent();
vm = new LoginViewModel();
BindingContext = vm;
}
private void connexion_click(object sender, EventArgs e)
{
Device.BeginInvokeOnMainThread(async () =>
{
await vm.Connexion();
});
}
}
您的VM应实施INotifyPropertyChanged
您的VM有一个递归的getter