-2

I'm new to WPF and Prism, so, I'm trying to figure very basic things out at the moment. My little experiment looks like this when running:

enter image description here

I have a Views\Registration.xaml that looks like this:

<UserControl x:Class="Configurator.Views.Registration"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:prism="http://prismlibrary.com/"             
             prism:ViewModelLocator.AutoWireViewModel="True">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="auto"/>
        </Grid.RowDefinitions>
        <Label Grid.Column="0" Grid.Row="0" Content="Email:" HorizontalContentAlignment="Right" Margin="6"/>
        <TextBox Grid.Column="1" Grid.Row="0" x:Name="email" Margin="6" Text="{Binding Email}"/>
        <Label Grid.Column="0" Grid.Row="1" Content="Password:" HorizontalContentAlignment="Right" Margin="6"/>
        <PasswordBox Grid.Column="1" Grid.Row="1" x:Name="password" Margin="6" />
        <Label Grid.Column="0" Grid.Row="2" Content="Password Confirmation:" HorizontalContentAlignment="Right" Margin="6"/>
        <PasswordBox Grid.Column="1" Grid.Row="2" x:Name="passwordConfirmation" Margin="6"/>
        <Button Grid.Column="1" Grid.Row="3" Content="Register" HorizontalAlignment="Left" Margin="6" Padding="6,2" Command="{Binding RegisterCommand}"/>
    </Grid>
</UserControl>

and then a ViewModels\RegistrationViewModel.cs that looks like this:

namespace Configurator.ViewModels {
    public class RegistrationViewModel : BindableBase {
        private string _email;
        public string Email {
            get { return _email; }
            set { SetProperty(ref _email, value); }
        }

        private string _password;
        public string Password {
            get { return _password; }
            set { SetProperty(ref _password, value); }
        }

        private string _passwordConfirmation;
        public string PasswordConfirmation {
            get { return _passwordConfirmation; }
            set { SetProperty(ref _passwordConfirmation, value); }
        }

        public DelegateCommand RegisterCommand { get; private set; }

        public RegistrationViewModel() {
            Console.WriteLine("RegistrationViewModel");
            RegisterCommand = new DelegateCommand(Register);
        }

        private void Register() {
            Console.WriteLine("Registering");
            Console.WriteLine($"Email: {Email}");
            Console.WriteLine($"Password: {Password}");
            Console.WriteLine($"Password Confirmation: {PasswordConfirmation}");
        }
    }
}

Should the Email, Password and PasswordConfirmation go into a model when following MVVM? If it should go into a model, how is the wiring done? I can't find any examples.

Pablo Fernandez
  • 279,434
  • 135
  • 377
  • 622
  • Why the downvotes? If someone asked me this question on a MVC app, such as Rails, the answer wouldn't be a matter of opinion and even then, how you wire a model to a view I don't think it's a matter of opinion. And if it is, pointing to the fact that MVVC is so loosely defined can be useful for other beginners as there's little up to date documentation out there. – Pablo Fernandez Sep 29 '18 at 09:29

3 Answers3

0

Your implementation looks all good to me, i.e. you bind to properties of a view model.

Sometimes people tend to refer to view models as "models" but the actual model would in this case be represented by a service that performs the actual registration.

You could inject you view model with an interface that this service implements and then call a method of the service through this interface in your Register() method, e.g.:

public class RegistrationViewModel : BindableBase
{
    ...
    private readonly IRegistrationService _registrationService;
    public RegistrationViewModel(IRegistrationService registrationService)
    {
        _registrationService = registrationService ?? throw new ArgumentNullException(nameof(registrationService));
        RegisterCommand = new DelegateCommand(Register);
    }

    private void Register()
    {
        _registrationService.Register(...);
    }
}
mm8
  • 163,881
  • 10
  • 57
  • 88
  • 1
    I don't know. Apparently somehow doesn't know MVVM...the now deleted answer might give a clue. – mm8 Sep 28 '18 at 11:56
  • 1
    +1 from me. This implementation also allows you to use either `DataTemplate` or `ControlTemplate` instead of the `UserControl`, which in my opinion is the last resort. – XAMlMAX Sep 28 '18 at 12:23
0

Since you are using MVVM, the properties should be in a Model. You then create a property of that Model in your ViewModel make it call the PropertyChanged-Event from INotifyPropertyChanged.

In the View you then bind the Element-Names of the Model-Property from your ViewModel.

You then just should decide wheter you make your Model implement INotifyPropertyChanged as well or you find another way.

BotMaster3000
  • 472
  • 4
  • 16
-1

Your ViewModel and your XAML are fine. Yes, you should expose the Email, Password etc. as part of the ViewModel.

The missing part in your example is the binding of the ViewModel to the UI. It is possible to achieve this by declaring it in your XAML, or in the constructor in the code-behind page you could have

public Registration(RegistrationViewModel model)
{
    DataContext = model;
}

What wiring are you enquiring about because it all looks pretty good to me.

  • 1
    I don't know why you were downvoted but the `DataContext` of the view is already set by the `prism:ViewModelLocator.AutoWireViewModel` attached property. – mm8 Sep 28 '18 at 11:55
  • 2
    Besides that, you should never explicity set the DataContext of a UserControl. The DataContext should either be inherited from its parent element, or automatically set by a framework like Prism. – Clemens Sep 28 '18 at 11:56
  • And again, @Clemens, I missed that too, I carried on blindly as if the XAML were for the Window – Bill Richards Sep 28 '18 at 11:59