2014-02-07 58 views
0

我正在學習使用MVVM設計模式的WPF,並試圖瞭解如何在代碼之外完成某些工作。 我有一個登錄頁面,如下圖所示。 enter image description hereMVVM模式查詢

我有一個密碼控制,我從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

[編輯補充樣本代碼]

繼承人一個簡單的代碼示例做你的榜樣不只是什麼,但在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)現在添加視圖模型將與視圖溝通,並提供它的命令接口和值:

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'的屬性。你如何執行'命令'ist由你決定。你可以像本教程那樣通過'RelayCommands'完成它,或者使用一個只實現'ICommand'接口並引用ViewModel的類。 MVVM的美妙之處在於,只要您遵守界面,View永遠不需要知道您如何處理'Click「事件。 –

3

要實現這一點,你應該綁定按鈕的命令是這樣 -

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

在您的視圖模型,此綁定像這樣創建一個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