Value Converter not working

DeepakSakpal.5527DeepakSakpal.5527 USMember ✭✭
edited December 2017 in Xamarin.Forms

I have a simple Converter which converts an array of string values to single string object i.e. joins all the strings using a separator. When the app is run, it hits the breakpoint in the value converter but not thereafter. It's not showing the concatenated string in a label as expected.

View:

<ContentPage 
    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>

View Code Behind:

using mvvm.ViewModels;
using Xamarin.Forms;

namespace mvvm.Views
{
    public partial class LoginPage : ContentPage
    {
        LoginViewModel viewModel = new LoginViewModel();

        public LoginPage()
        {
            InitializeComponent();

            this.BindingContext = viewModel;
        }
    }
}

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

Converter:

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));
        }
    }
}

Posts

  • CharwakaCharwaka INMember ✭✭✭✭✭

    are you getting any exception? are you type casting properly ? do check for which type your expecting

  • No. It worked when I made so changes related to List collection in the ViewModel. Tried to post the working ViewModel code, but somehow it's not getting posted.

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭
    Too much code... can you posta repo on github? You should use an observablecollection not a List when you use bindings....
  • CharwakaCharwaka INMember ✭✭✭✭✭

    @AlessandroCaliaro said:
    Too much code... can you posta repo on github? You should use an observablecollection not a List when you use bindings....

    well said

  • It worked after making few changes related to List object in the ViewModel. Here is the working code:

    using System.Windows.Input;
    using Xamarin.Forms;
    using mvvm.Models;
    using System.Collections.Generic;
    using XFPocketApp.Core.ViewModels;
    using XFPocketApp.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.");
                }
            }
        }
    }
    
  • It worked after making few changes related to List object in the ViewModel. Here is the working code

    using System.Windows.Input;
    using Xamarin.Forms;
    using mvvm.Models;
    using System.Collections.Generic;
    using XFPocketApp.Core.ViewModels;
    using XFPocketApp.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.");
                }
            }
        }
    }
    
  • It worked after making few changes related to List object in the ViewModel. Here is the working code

    using System.Windows.Input;
    using Xamarin.Forms;
    using mvvm.Models;
    using System.Collections.Generic;
    using XFPocketApp.Core.ViewModels;
    using XFPocketApp.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.");
                }
            }
        }
    }
    
Sign In or Register to comment.