Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Connecting to SQL Server using MVVM Pattern

0.00/5 (No votes)
13 Dec 2013 3  
The Model-View-ViewModel (MVVM) design pattern, why MVVM has to be used, and how to work with SQL Server using the MVVM design pattern.

Introduction

In this article, I would like to explain more about Model-View-ViewModel (MVVM) design pattern, why MVVM has to be used, and how to work with SQL Server using the MVVM design Pattern.

Rounded Rectangle: View

What is MVVM?

The MVVM pattern includes three key parts:

  • Model (Business rule, data access, model classes)
  • View (User interface (XAML))
  • ViewModel (Agent or middle man between view and model)

The ViewModel acts as an interface between Model and View. It provides data binding between View and model data as well as handles all UI actions by using command.

The View binds its control value to properties on a ViewModel, which, in turn, exposes data contained in Model objects.

Why use MVVM?

In traditional UI development - developer used to create a View using window or user control or page and then write all logical code (Event handling, initialization and data model, etc.) in the code behind and hence they were basically making code as a part of view definition class itself. This approach increased the size of the View class and created a very strong dependency between my UI and data binding logic and business operations. In this situation, no two developers can work simultaneously on the same view and also one developer's changes might break the other code. So everything is in one place is always a bad idea for maintainability, extendibility and testability prospective. So if you look at the big picture, you can feel that all these problems exist because there is a very tight coupling between the following items:

  • View (UI)
  • Model (Data displayed in UI)
  • Glue code (Event handling, binding, business logic)

In MVVM, the Glue code is View Model. So it basically focuses on separation of concerns to make the implementation of an application structure a lot simpler to create as well as maintain.

Getting Started

Step 1

Create a new class and add the following code to create a delegate command:

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; }
    }
}

Introduction to the ICommand Interface

Commands provide a mechanism for the view to update the model in MVVM architecture. Commands provide a way to search the element tree for a command handler. The ICommand interface is defined inside System.Windows.Input namespace. It has two methods and an event.

public bool CanExecute(object parameter)
public void Execute(object parameter)
public event EventHandler CanExecuteChanged

Execute method is only invoked when CanExecute returns true. In case CanExecute method returns false, then the binding control disables automatically.

In order to know CanExecute value listen to CanExecuteChanged event, that may vary based on parameter passed.

Task of CanExecuteChanged

CanExecuteChanged notifies any command sources (like a Button or CheckBox) that are bound to that ICommand that the value returned by CanExecute has changed. Command sources care about this because they generally need to update their status accordingly (e.g., a Button will disable itself if CanExecute() returns false).

The CommandManager.RequerySuggested event is raised whenever the CommandManager thinks that something has changed that will affect the ability of commands to execute. This might be a change of focus.

public event EventHandler CanExecuteChanged
{
    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }
}

Step 2

Create a new class and add the following code to create a 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.");
    }

Introduction to INotifyPropertyChanged Interface

The INotifyPropertyChanged interface is used to notify clients, typically binding clients that a property value has changed.

For example, consider a Person object with a property called FirstName. To provide generic property-change notification, the Person type implements the INotifyPropertyChanged interface and raises a PropertyChanged event when FirstName is changed.

For change notification to occur in a binding between a bound client and a data source, your bound type should either:

  • Implement the INotifyPropertyChanged interface (preferred)
  • Provide a change event for each property of the bound type

Do not do both.

Step 3

In MainWindow.xaml.cs, add the following code to initialize the ViewModel class and wrap the ViewModel to the View using the DataContext property.

DataContext = new CreateEmployeeViewModel();

Step 4

Add the following code in 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>

Note: Please look at Button Command property we are binding SaveCommand to communicate with the ICommand when the button was clicked.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here