65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 MVVM 模式连接到 SQL Server

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.32/5 (14投票s)

2013年12月10日

CPOL

3分钟阅读

viewsIcon

67814

downloadIcon

70

Model-View-ViewModel (MVVM) 设计模式,为什么需要使用 MVVM,以及如何使用 MVVM 设计模式与 SQL Server 交互。

引言

在本文中,我想详细解释 Model-View-ViewModel (MVVM) 设计模式,为什么需要使用 MVVM,以及如何使用 MVVM 设计模式与 SQL Server 交互。

Rounded Rectangle: View

什么是 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 的任何命令源(如 ButtonCheckBox),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 通信。

© . All rights reserved.