使用 MVVM 模式连接到 SQL Server






2.32/5 (14投票s)
Model-View-ViewModel (MVVM) 设计模式,为什么需要使用 MVVM,以及如何使用 MVVM 设计模式与 SQL Server 交互。
引言
在本文中,我想详细解释 Model-View-ViewModel (MVVM) 设计模式,为什么需要使用 MVVM,以及如何使用 MVVM 设计模式与 SQL Server 交互。
什么是 MVVM?
MVVM 模式包含三个关键部分:
Model
(业务规则、数据访问、模型类)View
(用户界面 (XAML))ViewModel
(View 和 Model 之间的代理或中间人)
ViewModel
充当 Model
和 View
之间的接口。 它提供 View
和模型数据之间的数据绑定,并通过使用命令处理所有 UI 操作。
View
将其控件值绑定到 ViewModel
上的属性,而 ViewModel
又公开包含在 Model
对象中的数据。
为什么使用 MVVM?
在传统的 UI 开发中,开发人员习惯于使用窗口、用户控件或页面创建 View
,然后将所有逻辑代码(事件处理、初始化和数据模型等)编写在代码隐藏中,因此他们基本上是将代码作为 View 定义类本身的一部分。 这种方法增加了 View
类的大小,并在 UI、数据绑定逻辑和业务操作之间创建了非常强的依赖关系。 在这种情况下,没有两个开发人员可以同时在同一个 View 上工作,并且一个开发人员的更改可能会破坏其他代码。 因此,将所有内容放在一个地方对于可维护性、可扩展性和可测试性来说总是一个坏主意。 因此,如果您从大局来看,您会感觉到所有这些问题都存在,因为以下项目之间存在非常紧密的耦合
View
(UI)Model
(UI 中显示的数据)- 胶合代码(事件处理、绑定、业务逻辑)
在 MVVM 中,胶合代码是 ViewModel。 因此,它基本上侧重于关注点分离,以使应用程序结构的实现更容易创建和维护。
入门
步骤 1
创建一个新类,并添加以下代码以创建委托命令
public class DelegateCommand : ICommand
{
private readonly Action _execute;
private readonly Func<bool> _canExecute;
public DelegateCommand(Action execute)
: this(execute, () => true)
{
_execute = execute;
}
public DelegateCommand(Action execute, Func<bool> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public void Execute(object parameter)
{
_execute();
}
public bool CanExecute(object parameter)
{
return _canExecute();
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
ICommand 接口简介
命令提供了一种机制,供 View 在 MVVM 架构中更新 Model。 命令提供了一种在元素树中搜索命令处理程序的方法。 ICommand
接口在 System.Windows.Input
命名空间内定义。 它有两个方法和一个事件。
public bool CanExecute(object parameter)
public void Execute(object parameter)
public event EventHandler CanExecuteChanged
仅当 CanExecute
返回 true
时,才会调用 Execute
方法。 如果 CanExecute
方法返回 false
,则绑定控件会自动禁用。
为了了解 CanExecute
值,请监听 CanExecuteChanged
事件,该事件可能因传递的参数而异。
CanExecuteChanged 的任务
CanExecuteChanged
通知绑定到该 ICommand
的任何命令源(如 Button
或 CheckBox
),CanExecute
返回的值已更改。 命令源关心这一点,因为它们通常需要相应地更新其状态(例如,如果 CanExecute()
返回 false
,则 Button
将禁用自己)。
每当 CommandManager
认为发生了一些会影响命令执行能力的变化时,就会引发 CommandManager.RequerySuggested
事件。 这可能是一个焦点变化。
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
第二步
创建一个新类,并添加以下代码以创建 ViewModel
public class CreateEmployeeViewModel : INotifyPropertyChanged
{
private string _id;
private string _firstName;
private string _address;
public CreateEmployeeViewModel()
{
SaveCommand = new DelegateCommand(Save, () => CanSave);
}
public string ID
{
get { return _id; }
set
{
_id = value;
NotifyOfPropertyChange("ID");
}
}
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
NotifyOfPropertyChange("FirstName");
}
}
public string Address
{
get { return _address; }
set
{
_address = value;
NotifyOfPropertyChange("Address");
}
}
public ICommand SaveCommand { get; private set; }
public bool CanSave
{
get { return !string.IsNullOrEmpty(ID) && !string.IsNullOrEmpty(FirstName); }
}
string connectionString =
@"Data Source=RAVINDRA\MSSQLSERVERS;Initial Catalog=CrudMethod;Integrated Security=SSPI;";
public void Save()
{
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = con.CreateCommand();
cmd.CommandText = "INSERT INTO Users(ID,FirstName,Address)VALUES(@ID,@FirstName,@Address)";
cmd.Parameters.AddWithValue("@ID", ID);
cmd.Parameters.AddWithValue("@FirstName", FirstName);
cmd.Parameters.AddWithValue("@Address", Address);
try
{
con.Open();
cmd.ExecuteNonQuery();
}
catch (SqlException ex)
{
throw ex;
}
finally
{
con.Close();
}
MessageBox.Show("Data Saved Successfully.");
}
INotifyPropertyChanged 接口简介
INotifyPropertyChanged
接口用于通知客户端(通常是绑定客户端)属性值已更改。
例如,考虑一个名为 FirstName
的属性的 Person
对象。 为了提供通用的属性更改通知,Person
类型实现了 INotifyPropertyChanged
接口,并在 FirstName
更改时引发 PropertyChanged
事件。
对于绑定客户端和数据源之间的绑定中发生的更改通知,您的绑定类型应
- 实现
INotifyPropertyChanged
接口(首选) - 为绑定类型的每个属性提供一个更改事件
两者不要同时做。
步骤 3
在 MainWindow.xaml.cs 中,添加以下代码以初始化 ViewModel
类,并使用 DataContext
属性将 ViewModel
包装到 View
中。
DataContext = new CreateEmployeeViewModel();
步骤 4
在 MainWindow.xaml 中添加以下代码
<Window x:Class="WpfTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Helloworld" Height="350" Width="525">
<Grid>
<Button x:Name="btnSave"
HorizontalAlignment="Left"
TabIndex="100"
Content="Save"
Width="100"
Height="30"
Margin="100,0,100,0"
Command="{Binding Path= SaveCommand}" />
<TextBox Height="23"
HorizontalAlignment="Left" Margin="114,26,0,0"
Name="txtID" VerticalAlignment="Top"
Width="120" Text="{Binding ID}"/>
<TextBox Height="23"
HorizontalAlignment="Left" Margin="114,55,0,0"
Name="txFirstName" VerticalAlignment="Top"
Width="120" Text="{Binding FirstName }" />
<TextBox Height="23"
HorizontalAlignment="Left" Margin="114,84,0,0"
Name="txtAddress" VerticalAlignment="Top"
Width="120" Text="{Binding Address}" />
<Label Content="ID:" Height="28"
HorizontalAlignment="Left"
Margin="84,26,0,0" Name="label1"
VerticalAlignment="Top" />
<Label Content="First Name:" Height="28"
HorizontalAlignment="Left"
Margin="40,50,0,0" Name="label2"
VerticalAlignment="Top" />
<Label Content="Address:" Height="28"
HorizontalAlignment="Left"
Margin="53,75,0,0" Name="label3"
VerticalAlignment="Top" />
</Grid>
</Window>
注意:请查看 Button Command 属性,我们正在绑定 SaveCommand
以在单击按钮时与 ICommand
通信。