而是背後實施的代碼按鈕單擊處理程序中,使用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到解決方案被打開。:-)
非常感謝,這使得事情分配cl earer。這是否意味着,我將事件處理程序放入的任何類都是View模型?任何我想用於視圖的方法都可以進入同一個類,並且這會自動成爲viewModel?謝謝 –
@EPOColla:在你的例子中我會說是。但EventHandlers和方法不會「自動」組成ViewModel。理想情況下,你構造你的類,以便ViewModel是唯一直接**與View進行通信的類(拋開這個規則的一些例外,例如Converters,Behaviors,...)。 –
這使您可以選擇以多種方式實施此類處理。例如,ViewModel可能會提供一個包含'Command'的屬性。你如何執行'命令'ist由你決定。你可以像本教程那樣通過'RelayCommands'完成它,或者使用一個只實現'ICommand'接口並引用ViewModel的類。 MVVM的美妙之處在於,只要您遵守界面,View永遠不需要知道您如何處理'Click「事件。 –