值转换器无法正常工作

时间:2017-12-26 07:33:15

标签: xamarin.forms ivalueconverter

我有一个简单的转换器,它将字符串值数组转换为单个字符串对象,即使用分隔符连接所有字符串。当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));
        }
    }
}

1 个答案:

答案 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.");
            }
        }
    }
}