2014-02-07 5 views
0

Я изучаю WPF с шаблоном проектирования MVVM и пытаюсь понять, как сделать некоторые вещи за пределами кода. У меня есть страница входа, изображенная ниже. enter image description hereMVVM Pattern Query

У меня есть контроль пароля, который я взял с http://www.wpftutorial.net/PasswordBox.html.

На данный момент я хотел бы рассказать вам, как правильно спросить, соответствует ли мой код правильному классу/правилу, чтобы соблюдать правила MVVVM с разделом проблем.

У меня есть инструкция if, чтобы проверить, соответствуют ли данные строке имени и строке пароля. Код указан в коде. Мне просто интересно, правильно ли это относится к MVVM. Интересно, как вы реализуете это в ViewModel?

private void OK_Click(object sender, RoutedEventArgs e) 
{ 
    if (emp.Name == "ep" && emp.Password == "pass") 
    { 
     MessageBox.Show("namd and Pw accepted"); 
     //open new page 
     var HomeScreen = new HomeScreen(); 
     HomeScreen.Show(); 
    } 
    else 
    { 
     //deny access 
     MessageBox.Show("Incorrect username and password"); 
    } 
} 

ответ

3

Вместо реализации щелчка кнопки обработчик в коде позади, использовать ICommand и привязать его к событию кнопки в XAML.

Вот действительно отличный учебник, который получил меня начиная с MVVM: WPF Apps With The Model-View-ViewModel Design Pattern

[Отредактировано добавить пример кода]

Heres простой пример кода, чтобы сделать только то, что ваш пример делает, но в стиле MVVM и без кода кода вообще.

1) Создайте новое решение WPF, для этого небольшого примера я назвал его просто «WpfApplication».

2) Отредактируйте код автоматически созданный MainWindow.xaml:

<Window x:Class="WpfApplication.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:viewModel="clr-namespace:WpfApplication" 
     Title="MainWindow" Height="234" Width="282"> 

    <!-- Create the ViewModel as the initial DataContext --> 
    <Window.DataContext> 
    <viewModel:MainWindowViewModel /> 
    </Window.DataContext> 

    <Grid> 
    <TextBox Height="23" 
      HorizontalAlignment="Left" 
      Margin="70,31,0,0" 
      Name="textBox1" 
      VerticalAlignment="Top" 
      Width="120" 
      Text="{Binding Path=Name}"/> 
    <TextBox Height="23" 
      HorizontalAlignment="Left" 
      Margin="70,72,0,0" 
      Name="textBox2" 
      VerticalAlignment="Top" 
      Width="120" 
      Text="{Binding Path=Password}" /> 
    <Label Content="Name" 
      Height="28" 
      HorizontalAlignment="Left" 
      Margin="22,29,0,0" 
      Name="label1" 
      VerticalAlignment="Top" /> 
    <Label Content="PW" 
      Height="28" 
      HorizontalAlignment="Left" 
      Margin="22,70,0,0" 
      Name="label2" 
      VerticalAlignment="Top" /> 
    <Button Content="OK" 
      Height="23" 
      HorizontalAlignment="Left" 
      Margin="70,119,0,0" 
      Name="button1" 
      VerticalAlignment="Top" 
      Width="120" 
      Command="{Binding Path=LoginCommand}" 
      CommandParameter="{Binding Path=.}" 
      /> 
    </Grid> 
</Window> 

(Игнорируйте ширина, высота, значения полей, они просто копируются & вставленный из моего дизайнера и были быстро & грязный доводят до примерно выглядеть как ваш скриншот ;-))

3) Создайте класс Command, который будет обрабатывать логический логин. Обратите внимание, что я не выполнил его как RelayCommand, как в учебнике Джоша Смита, но это было бы легко изменить код соответственно:

 namespace WpfApplication 
     { 
     using System; 
     using System.Windows; 
     using System.Windows.Input; 

     /// <summary> 
     /// Checks the user credentials. 
     /// </summary> 
     public class LoginCommand : ICommand 
     { 

      /// <summary> 
      /// Defines the method to be called when the command is invoked. 
      /// </summary> 
      /// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param> 
      public void Execute(object parameter) 
      { 
       MainWindowViewModel viewModel = parameter as MainWindowViewModel; 

       if (viewModel == null) 
       { 
       return; 
       } 

       if (viewModel.Name == "ep" && viewModel.Password == "pass") 
       { 
       MessageBox.Show("namd and Pw accepted"); 

       //open new page 
       var HomeScreen = new HomeScreen(); 
       HomeScreen.Show(); 
       } 
       else 
       { 
       //deny access 
       MessageBox.Show("Incorrect username and password"); 
       } 
      } 

      /// <summary> 
      /// Defines the method that determines whether the command can execute in its current state. 
      /// </summary> 
      /// <returns> 
      /// true if this command can be executed; otherwise, false. 
      /// </returns> 
      /// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param> 
      public bool CanExecute(object parameter) 
      { 
       // Update this for your application's needs. 
       return true; 
      } 

      public event EventHandler CanExecuteChanged; 
     } 
    } 

4) Теперь добавьте ViewModel, который будет взаимодействовать с видом и предоставить ему команду интерфейс и значения:

namespace WpfApplication 
    { 
     using System; 
     using System.Collections.Generic; 
     using System.ComponentModel; 
     using System.Linq; 
     using System.Text; 
     using System.Windows.Input; 

     /// <summary> 
     /// TODO: Update summary. 
     /// </summary> 
     public class MainWindowViewModel : INotifyPropertyChanged 
     {  
      #region Implementation of INotifyPropertyChanged 

      /// <summary> 
      /// Occurs when a property value changes. 
      /// </summary> 
      public event PropertyChangedEventHandler PropertyChanged; 

      /// <summary> 
      /// Signal that the property value with the specified name has changed. 
      /// </summary> 
      /// <param name="propertyName">The name of the changed property.</param> 
      protected virtual void OnPropertyChanged(string propertyName) 
      { 
      if (this.PropertyChanged != null) 
      { 
       this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
      } 

      #endregion Implementation of INotifyPropertyChanged 

      #region Backing Fields 

      /// <summary> 
      /// Gets or sets the value of Name. 
      /// </summary> 
      private string name; 

      /// <summary> 
      /// Gets or sets the value of Password. 
      /// </summary> 
      private string password; 

      /// <summary> 
      /// Gets or sets the value of LoginCommand. 
      /// </summary> 
      private LoginCommand loginCommand; 

      #endregion Backing Fields 

      #region Constructor 

      /// <summary> 
      /// Initializes a new instance of the <see cref="MainWindowViewModel"/> class. 
      /// </summary> 
      public MainWindowViewModel() 
      { 
      this.loginCommand = new LoginCommand(); 
      } 

      #endregion Constructor 

      #region Properties 

      /// <summary> 
      /// Gets or sets the name of the user. 
      /// </summary> 
      public string Name 
      { 
      get 
      { 
       return this.name; 
      } 

      set 
      { 
       if (this.name == value) 
       { 
        return; 
       } 

       this.name = value; 
       this.OnPropertyChanged("Name"); 
      } 
      } 

      /// <summary> 
      /// Gets or sets the user password. 
      /// </summary> 
      public string Password 
      { 
      get 
      { 
       return this.password; 
      } 

      set 
      { 
       if (this.password == value) 
       { 
        return; 
       } 

       this.password = value; 
       this.OnPropertyChanged("Password"); 
      } 
      } 

      /// <summary> 
      /// Gets or sets the command object that handles the login. 
      /// </summary> 
      public ICommand LoginCommand 
      { 
      get 
      { 
       return this.loginCommand; 
      } 

      set 
      { 
       if (this.loginCommand == value) 
       { 
        return; 
       } 

       this.loginCommand = (LoginCommand)value; 
       this.OnPropertyChanged("LoginCommand"); 
      } 
      } 

      #endregion Properties 
     } 
    } 

5) Наконец, не забудьте добавить дополнительное окно HomeScreen, который будет открыт в LoginCommand к решению.:-)

+0

Большое спасибо, что заставляет вещи выделять cl earer. Означает ли это, что любой класс, в который я помещал обработчик событий, является моделью View? И любые методы, которые я хочу использовать с представлением, могут перейти в один класс, и это автоматически будет viewModel? Спасибо –

+0

@EPOColla: В вашем примере я бы сказал «да». Но EventHandlers и методы не «автоматически» составляют ViewModel. В идеале вы структурируете свои классы, чтобы ViewModel был единственным классом ** напрямую ** обмениваться данными с View (некоторые исключения этого правила в стороне, например, Converters, Behaviors, ...). –

+0

Это дает вам возможность реализовать такую ​​обработку несколькими способами. Например, ViewModel может предоставить свойство, содержащее 'Command'. Как вы реализуете 'Command' ist до вас. Вы можете сделать это с помощью «RelayCommands», как в учебнике, или использовать класс, который только реализует интерфейс «ICommand» и ссылается на него с ViewModel. Красота MVVM заключается в том, что View никогда не должен знать о том, как вы обрабатываете событие Click, если вы придерживаетесь интерфейса. –

3

Чтобы осуществить это, необходимо связать команду баттона, как это -

<Button Content ="OK" Command = {Binding OKCommand} /> 

В вашей ViewModel, создать свойство ICommand для этого связывания, как это -

public class MyViewModel() : INotifyPropertyChanged 
{ 

ICommand _OKCommand; 
public ICommand OKCommad 
{ 
    get { return _OKCommand; } 
    set { _OKCommand = value; PropertyChanged(OKCommad); } 
} 

public MyViewModel() 
{ 
    this.OKCommand += new DelegateCommand(OKCommand_Execute); 
} 

public void OKCommand_Execute() 
{ 
// Code for button click here 
} 

} 

Также обратите внимание на что для использования этой команды делегата вам необходимо добавить ссылку на Microsoft.Practices.Prism.dll

Смежные вопросы