我有一个简单的转换器,它将字符串值数组转换为单个字符串对象,即使用分隔符连接所有字符串。当app运行时,它会触及值转换器中的断点,但之后不会。它没有按预期在标签中显示连接的字符串。
查看:
<?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="mvvm.Views.LoginPage"
xmlns:converters="clr-namespace:XFApp.Core.Converters;assembly=XFApp.Core">
<ContentPage.Resources>
<ResourceDictionary>
<converters:ValidationErrorConverter x:Key="validationErrorConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout Padding="10,100,10,10">
<StackLayout>
<Label
Text="{Binding Errors, Converter={StaticResource validationErrorConverter}}" />
<Label Text="User name:" />
<Entry x:Name="entryUsername" Keyboard="Email" Text="{Binding Username, Mode=TwoWay}" Style="{StaticResource EntryStyle}" />
<Label Text="Password:" />
<Entry x:Name="entryPassword" IsPassword="true" Text="{Binding Password, Mode=TwoWay}" Style="{StaticResource EntryStyle}" />
</StackLayout>
<Button VerticalOptions="EndAndExpand" Text="LOGIN" Command="{Binding AuthenticateUserCommand}" />
</StackLayout>
</ContentPage>
查看代码背后:
using mvvm.ViewModels;
using Xamarin.Forms;
namespace mvvm.Views
{
public partial class LoginPage : ContentPage
{
LoginViewModel viewModel = new LoginViewModel();
public LoginPage()
{
InitializeComponent();
this.BindingContext = viewModel;
}
}
}
视图模型:
using System.Windows.Input;
using Xamarin.Forms;
using mvvm.Models;
using System.Collections.Generic;
using XFApp.Core.ViewModels;
namespace mvvm.ViewModels
{
public class LoginViewModel : ViewModelBase
{
private string _username;
private string _password;
private bool _isValid;
private IList<string> _errors;
public LoginViewModel()
{
_username = "";
_password = "";
_errors = new List<string>();
}
public IList<string> Errors
{
set { SetProperty(ref _errors, value); }
get { return _errors; }
}
public string Username {
set {
SetProperty(ref _username, value);
((Command)AuthenticateUserCommand).ChangeCanExecute();
}
get { return _username; }
}
public string Password
{
set {
SetProperty(ref _password, value);
((Command)AuthenticateUserCommand).ChangeCanExecute();
}
get { return _password; }
}
public bool IsValid
{
set { SetProperty(ref _isValid, value); }
get { return _isValid; }
}
public ICommand AuthenticateUserCommand => new Command(
execute: () => {
AuthenticateUserAsync();
}
//,
//canExecute: () => {
// return (Username.Length > 0);
//}
);
private bool Validate()
{
if (_username == "")
{
_errors.Add("An e-mail address is required.");
Errors = _errors;
}
if (_password == "")
{
_errors.Add("A password is required.");
Errors = _errors;
}
return _errors.Count == 0;
}
private async void AuthenticateUserAsync()
{
Errors.Clear();
IsValid = true;
bool isValid = Validate();
bool isAuthenticated = false;
Token token = null;
if (!isValid)
{
IsValid = false;
return;
}
token = await Services.UserService.IsValidUser(_username, _password);
if (token != null)
isAuthenticated = true;
if (isAuthenticated)
{
//new Messenger().Subscribe<LoginFailedMessage>(this, loginPage.LoginFailed);
//MainPage = new NavigationPage(new mvvmPage());
}
else
{
//Errors.Clear();
//Errors.Add("Invalid credentials.");
}
}
}
}
转换器:
using System;
using System.Collections.Generic;
using System.Globalization;
using Xamarin.Forms;
namespace XFApp.Core.Converters
{
public class ValidationErrorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
List<string> errors = value as List<string>;
return errors != null && errors.Count > 0 ? string.Join("\r\n", errors.ToArray()) : "";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
ViewModelBase:
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace XFApp.Core.ViewModels
{
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected 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));
}
}
}
答案 0 :(得分:0)
在我对ViewModel中与List对象相关的代码进行了一些更改后,它工作了。如果有人需要,这是工作代码。
using System.Windows.Input;
using Xamarin.Forms;
using mvvm.Models;
using System.Collections.Generic;
using XFApp.Core.ViewModels;
using XFApp.Core.Navigation;
namespace mvvm.ViewModels
{
public class LoginViewModel : ViewModelBase, IViewModel
{
private string _username;
private string _password;
private bool _isValid;
private List<string> _errors;
INavigationService _navService;
public LoginViewModel()
{
_navService = NavigationService.Instance;
_username = "";
_password = "";
_errors = new List<string>();
}
public List<string> Errors
{
set { SetProperty(ref _errors, value); }
get { return _errors; }
}
public string Username {
set {
SetProperty(ref _username, value);
((Command)AuthenticateUserCommand).ChangeCanExecute();
}
get { return _username; }
}
public string Password
{
set {
SetProperty(ref _password, value);
((Command)AuthenticateUserCommand).ChangeCanExecute();
}
get { return _password; }
}
public bool IsValid
{
set { SetProperty(ref _isValid, value); }
get { return _isValid; }
}
public ICommand AuthenticateUserCommand => new Command(
execute: () => {
AuthenticateUserAsync();
}
//,
//canExecute: () => {
// return (Username.Length > 0);
//}
);
private bool Validate()
{
List<string> errors = new List<string>();
if (_username == "")
errors.Add("An e-mail address is required.");
if (_password == "")
errors.Add("A password is required.");
Errors = errors;
return _errors.Count == 0;
}
private async void AuthenticateUserAsync()
{
Errors.Clear();
IsValid = true;
bool isValid = Validate();
bool isAuthenticated = false;
Token token = null;
if (!isValid)
{
IsValid = false;
return;
}
token = await Services.UserService.IsValidUser(_username, _password);
if (token != null)
isAuthenticated = true;
if (isAuthenticated)
{
await _navService.PushAsync<MVVMPageViewModel>();
await _navService.RemoveLastFromBackStackAsync();
}
else
{
//Errors.Clear();
//Errors.Add("Invalid credentials.");
}
}
}
}