2

Actual state: I click in the Login Button and the ViewModel changes to the new View.

Desired state: I click the LoginButton (the LoginViewModel binds the with the view to get the Email and Password and verifies in the server the authenticity of the user and if its ok the request receives as answer the info about the user and changes the view)

What I know: change the views, bind the textbox, communication with the server (handling the request and the answers)

What I don't know: send from the LoginViewModel to the GeneralViewModel the answer with the info about the user, don't know how to maintain the PasswordBox instead of the TextBox for binding.

CODE: LoginView

<Grid Margin="0,0,-74.4,-11.8" HorizontalAlignment="Left" Width="800" Height="600" VerticalAlignment="Top">

    <TextBox Text = "{Binding Email, Mode = TwoWay}" Style="{DynamicResource MyTextBox}" x:Name="textBoxEmail" VerticalContentAlignment="Bottom" HorizontalContentAlignment="Center" HorizontalAlignment="Center"  Width="248" Margin="274,212,278,347" FontFamily="Segoe UI Semibold" />

    <Image Source="C:\Users\Images\logo.png" x:Name="Logo" HorizontalAlignment="Left" Height="129" Margin="301,63,0,0" VerticalAlignment="Top" Width="151" RenderTransformOrigin="0.5,0.5">
        <Image.RenderTransform>
            <TransformGroup>
                <ScaleTransform/>
                <SkewTransform/>
                <RotateTransform Angle="0.091"/>
                <TranslateTransform/>
            </TransformGroup>
        </Image.RenderTransform>
    </Image>

Sign up now! Forgot your Password? Click here!

LoginViewModel

 class LoginViewModel : AViewModel
{
    WifiAP wa;
    #region fields
    private string _email = null;
    private TokenRequest tk;
    public DelegateCommand LoginCommand { get; set; }

    public string Email
    {
        get
        {
            return _email;
        }
        set
        {
            _email = value;
            OnPropertyChanged("Email");
            //Here's the magic
            LoginCommand.RaiseCanExecuteChanged();
        }
    }
    private string _password = null;

    public string Password
    {
        get
        {
            return _password;
        }
        set
        {
            _password = value;
            OnPropertyChanged("Password");
            //Here's the magic
            LoginCommand.RaiseCanExecuteChanged();
        }
    }
    public string mac;
    #endregion

    public LoginViewModel()
    {
        wa = new WifiAP();
        LoginCommand = new DelegateCommand(Login, CanLogin);

    }

    public bool CanLogin()
    {
        return !string.IsNullOrEmpty(Email);
    }

    public void Login()
    {
        //
    }


    #region auxiliaryMethods
    public string getMac()
    {
        mac = wa.GetMACAddress();
        return mac;
    }

    public string hashingMD5(string pass)
    {
        string pwd = pass;
        System.Security.Cryptography.MD5 hs = System.Security.Cryptography.MD5.Create();
        byte[] db = hs.ComputeHash(System.Text.Encoding.UTF8.GetBytes(pwd));
        string result = Convert.ToBase64String(db);
        return result;
    }}

MainViewModel

    public MainWindowViewModel{ 
this.AddViewModel(new LoginViewModel() { DisplayName = "Login", InternalName = "LoginViewModel" }); 
this.AddViewModel(new GeneralViewModel() { DisplayName = "General", InternalName = "GeneralViewModel" }); 
this.Current_ViewModel = this.GetViewModel("LoginViewModel");

Thanks in advance for your time.

Antoine
  • 312
  • 1
  • 5
  • 18
  • I think you are making it a little bit hard for yourself. It would be easier if you'd use BindableBase as base class for your ViewModels and RegionManager with RequestNavigate(target, parameter) method for whole navigation. You can get everything by installing NuGet package Prism.Core. Can you please specify the content of Login method? How do you change the Views without RegionManager? – Michał J. Gąsior Apr 27 '16 at 12:50
  • Hi @mikes thanks for your time. I have installed the MVVM Light and use some stuff, but I'm still learning this new architecture and it is still a mess in my brain the concepts. And I'm grinding in the stackoverflow trying to understand some concepts but I'm having a lot of trouble. To answer your first question, I have the email and the password. – Antoine Apr 28 '16 at 13:59
  • I would like to know how are you going to change the View after invoking Login method in your LoginViewModel class. – Michał J. Gąsior Apr 29 '16 at 10:21
  • I was changing the views just for testing using this: Binding DataContext.SelectViewCommand, ElementName=MainWindowView}" CommandParameter="GeneralViewModel" ... And in the MainWindowViewModel : this.AddViewModel(new LoginViewModel() { DisplayName = "Login", InternalName = "LoginViewModel" }); this.AddViewModel(new GeneralViewModel() { DisplayName = "General", InternalName = "GeneralViewModel" }); this.Current_ViewModel = this.GetViewModel("LoginViewModel"); – Antoine Apr 29 '16 at 10:32
  • If you can, edit the main question. It will help with formatting and readability. :) – Michał J. Gąsior Apr 29 '16 at 10:45
  • @mikes I already modified. It's more clear now? :) – Antoine Apr 29 '16 at 12:31
  • I think yes. :) Thank you. – Michał J. Gąsior Apr 30 '16 at 17:01

1 Answers1

0

At first, here you have the article that tells you what and how to cope with PasswordBox in MVVM. Secondly, how to pass the data through? I'm not very familiar with MVVM Light because I personally use PRSIM. You may though do something alike RegionContext.

At first you have to create a class as your RegionData. Notice, that this model also implements the OnPropertyChanged interface (the implementation comes form inherited ViewModelBase in MVVM Light).

public class HaveLoginData : ViewModelBase
{
    private string _login;
    public string Login
    {
        get { return _login; }
        set
        {
            _login = value;
            RaisePropertyChanged(() => Login);
        }
    }
}

Than, in the constructor you should make a common instance of this class for both of your ViewModels:

    public MainWindowViewModel
    { 
        var regionData = new HaveLoginData();
        this.AddViewModel(new LoginViewModel() { RegionData = regionData }); 
        this.AddViewModel(new GeneralViewModel() { RegionData = regionData }); 
        this.Current_ViewModel = this.GetViewModel("LoginViewModel");
    }

You will also have to add a new property to your ViewModels called RegionData:

using System.ComponentModel;

namespace YourApp.ViewModels
{
    public class GeneralViewModel
    {
        private HaveLoginData _regionData;
        public HaveLoginData RegionData
        {
            get { return _regionData; }
            set
            {
                _regionData = value;
                _regionData.PropertyChanged += _regionData_PropertyChanged;
            }
        }

        private void _regionData_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "Login")
            {
                // do the second view model login logic
            }
        }
    }
}

And the Login ViewModel:

namespace YourApp.ViewModels
{
    public class LoginViewModel
    {
        public HaveLoginData RegionData { get; set; }

        public void Login()
        {
            // do the login conditions logic
            if (true)
            {
                RegionData.Login = "new user login";
            }
        }
    }
}

As you can see, when someone will set the RegionData, you will subscribe to the PropertyChanged event and be noticed in every ViewModel about the changes inside the Login and MD5Password properties. As you see, you also have to remeber about unsubscribing from the PropertyChanged event from your previous RegionData. The RegionData once created should not be changed, so it may not be neccessary to do it in the setter (you can make some kind of Dispose to delete the reference).

Community
  • 1
  • 1
Michał J. Gąsior
  • 1,457
  • 3
  • 21
  • 39
  • The OnRegionDataChanged method is not invoked? Do you have your LoginViewModel code somewhere I can see it? – Michał J. Gąsior May 01 '16 at 23:46
  • Are you sure you have set the same RegionData in both ViewModels? I have edited the part with MainWindowViewModel constructor to emphasize this. Do you get the same instance of LoginViewModel when you invoke this.GetViewModel("LoginViewModel");? RegionData is not null? – Michał J. Gąsior May 02 '16 at 13:11
  • I feel like dying here :( I've tried to implement but when I put in the GeneralViewModel it says that does not contain a definition for RegionData, but when I try to implement in the ViewModel it says I've already implemented in the namespace... – Antoine May 02 '16 at 14:16
  • I have corrected the solution. Try now - I have make some edits in the view models and the region data. – Michał J. Gąsior May 02 '16 at 18:32