Click here to Skip to main content
15,867,324 members
Articles / Desktop Programming / WPF

Connecting to SQL Server using MVVM Pattern

Rate me:
Please Sign up or sign in to vote.
2.32/5 (14 votes)
13 Dec 2013CPOL3 min read 64.3K   12   14
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:

C#
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.

C#
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.

C#
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:

C#
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.

C#
DataContext = new CreateEmployeeViewModel();

Step 4

Add the following code in MainWindow.xaml:

XML
<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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Comments and Discussions

 
QuestionThanks its very useful..! Pin
Member 1267486231-Oct-16 0:53
Member 1267486231-Oct-16 0:53 
QuestionButton Disabled Pin
Lucas Pavese14-Mar-16 5:05
Lucas Pavese14-Mar-16 5:05 
QuestionLink download Pin
Phi9-Dec-15 15:58
Phi9-Dec-15 15:58 
BugCode is not working Pin
Member 1130232714-Dec-14 21:44
Member 1130232714-Dec-14 21:44 
GeneralMy vote of 1 Pin
johannesnestler16-Jul-14 1:17
johannesnestler16-Jul-14 1:17 
Questioncan't download source code Pin
priom2227-Apr-14 9:37
priom2227-Apr-14 9:37 
GeneralMy vote of 3 Pin
fredatcodeproject13-Dec-13 5:34
professionalfredatcodeproject13-Dec-13 5:34 
Question[My vote of 1] Incorrect example... Pin
SledgeHammer0113-Dec-13 5:03
SledgeHammer0113-Dec-13 5:03 
QuestionSource code file missing Pin
Tridip Bhattacharjee12-Dec-13 20:16
professionalTridip Bhattacharjee12-Dec-13 20:16 
GeneralMy vote of 1 Pin
cjb11010-Dec-13 21:31
cjb11010-Dec-13 21:31 
GeneralRe: My vote of 1 Pin
cjb11010-Dec-13 21:35
cjb11010-Dec-13 21:35 
GeneralMy vote of 2 Pin
Klaus Luedenscheidt10-Dec-13 18:55
Klaus Luedenscheidt10-Dec-13 18:55 
GeneralMy vote of 3 Pin
leiyangge10-Dec-13 14:39
leiyangge10-Dec-13 14:39 
QuestionSeems something for newbie Pin
leiyangge10-Dec-13 14:38
leiyangge10-Dec-13 14:38 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.