我正在学习使用MVVM设计模式的WPF,并试图了解如何在代码之外完成一些事情。 我有一个登录页面,如下图所示。
我从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");
}
}
答案 0 :(得分:2)
不是在后面的代码中实现按钮单击处理程序,而是使用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类。请注意,我没有像Josh Smith的教程那样将它实现为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)现在添加将与View通信的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)最后,不要忘记添加一个将由LoginCommand打开到解决方案的其他窗口HomeScreen
。 : - )
答案 1 :(得分:2)
要实现这一点,你应该像这样绑定按钮的命令 -
<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
的引用