Silverlight Telerik Editable GridView with MVVM – Part 3

This is the final part of the Telerik Editable GridView Series. In Part 1 I talked about the Model and in Part 2 I covered the View Model. In this post I will be discussing the View portion of the MVVM pattern.

I will start out with the xaml for the GridView.

[sourcecode language=’vb’]

xmlns:telerikGridView=”clr-namespace:Telerik.Windows.Controls;
assembly=Telerik.Windows.Controls.GridView”
xmlns:telerikData=”clr-namespace:Telerik.Windows.Controls;
assembly=Telerik.Windows.Controls.Data”

[/sourcecode]

[sourcecode language=’xml’]





















[/sourcecode]

I bind the GridView item source to the “EmployeeList” in the View Model. Each column is bound to a property on the Employee Model. Since my model implements System.ComponentModel.INotifyPropertyChanged, the GridView is updated each time any property that I am bound to on the model changes. I used a templated column to represent the “IsActive” boolean column. For the templated column I specify binding in each of the cell templates and on the column. The binding on the column is used by the GridView for filtering and sorting.

Next, I will go through the code-behind of the View.

[sourcecode language=’vb’]

Partial Public Class EmployeeMaintenancePage
Inherits UserControl

Private _vm As EmployeeMaintenanceViewModel

”’

”’ Constructor
”’

”’
Public Sub New()
InitializeComponent()
End Sub

#Region “Event Handlers”

”’

”’ I clear my sort and filter before adding a new Employee. This is
”’ necessary because if the new row does not fit the current filter, it
”’ will not display. Also, by clearing the sort, we force the newly added
”’ row to the bottom of the grid.
”’

”’ ”’ ”’
Private Sub EmployeeGridView_AddingNewDataItem(ByVal sender As System.Object, ByVal e As Telerik.Windows.Controls.GridView.GridViewAddingNewEventArgs)
EmployeeGridView.FilterDescriptors.Clear()
EmployeeGridView.SortDescriptors.Clear()
e.NewObject = _vm.GetNewEmployee()
End Sub

”’

”’ Reload from the row cache if edit was cancelled, otherwise
”’ save to the database.
”’

”’ ”’ ”’
Private Sub EmployeeGridView_RowEditEnded(ByVal sender As System.Object, ByVal e As Telerik.Windows.Controls.GridViewRowEditEndedEventArgs)
If e.EditAction = Telerik.Windows.Controls.GridView.GridViewEditAction.Cancel Then
_vm.ReloadEmployeeFromCache(CType(e.Row.DataContext, EmployeeModel))
Else
_vm.UpdateEmployee(TryCast(e.Row.DataContext, EmployeeModel))
End If
End Sub

”’

”’ Call the delete method on the View Model to delete employee. GridView will get
”’ updated when the item is removed from the “EmployeeList” on the view model.
”’

”’ ”’ ”’
Private Sub EmployeeGridView_Deleting(ByVal sender As System.Object, ByVal e As Telerik.Windows.Controls.GridViewDeletingEventArgs)
_vm.DeleteEmployee(CType(e.Items(0), EmployeeModel).Id)
e.Cancel = True
End Sub

”’

”’ Store the current copy of the row on Selection Changed. In a case when an edit
”’ is cancelled, the stored value is used to reload row with original values.
”’

”’ ”’ ”’
Private Sub EmployeeGridView_SelectionChanged(ByVal sender As System.Object, ByVal e As Telerik.Windows.Controls.SelectionChangeEventArgs)
If e.AddedItems.Count > 0 Then
_vm.CurrentRowCache = CType(e.AddedItems(0), EmployeeModel).Clone()
End If
End Sub
#End Region

#Region “Public Methods”

”’

”’ Load the View Model and bind it to the View.
”’

”’
Public Sub Load()
_vm = New EmployeeMaintenanceViewModel()
_vm.Load()
Me.DataContext = _vm
End Sub

#End Region

End Class

[/sourcecode]

In the code-behind of the View, I mainly handle the events and call my View Model to process the logic. This allows me to unit test the logic in my View Model.

Silverlight Telerik Editable GridView with MVVM – Part 1

Over last few days I’ve been working with the Telerik GridView control in a Silverligt 3 project. The goal was to implement an editable grid using MVVM (Model-View-View Model) pattern. A user must be able to Add/Edit/Delete rows from the grid.

I will be using the Telekik controls version 2009.3.1208.1030

I will start by creating my Model.

Model
  1. Imports System.Globalization
  2. Imports System.ComponentModel
  3. Imports System.ComponentModel.DataAnnotations
  4.  
  5. Public Class EmployeeModel
  6.     Implements INotifyPropertyChanged
  7.  
  8.     Public Sub New()
  9.  
  10.     End Sub
  11.  
  12.     Public Sub New()
  13.         ._isModified = False
  14.         ._isDeleted = False
  15.         ._isNew = False
  16.     End Sub
  17.  
  18.     Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
  19.  
  20.     Protected Sub NotifyPropertyChanged(ByVal propertyName As String)
  21.         RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
  22.     End Sub
  23.  
  24.     Private _isModified As Boolean
  25.     Public Property IsModified() As Boolean
  26.         Get
  27.             Return (_isModified)
  28.         End Get
  29.         Set(ByVal value As Boolean)
  30.             _isModified = value
  31.             NotifyPropertyChanged("IsModified")
  32.         End Set
  33.     End Property
  34.  
  35.     Private _isDeleted As Boolean
  36.     Public Property IsDeleted() As Boolean
  37.         Get
  38.             Return _isDeleted
  39.         End Get
  40.         Set(ByVal value As Boolean)
  41.             _isDeleted = value
  42.             NotifyPropertyChanged("IsDeleted")
  43.         End Set
  44.     End Property
  45.  
  46.     Private _id As Integer
  47.     Public Property Id() As Integer
  48.         Get
  49.             Return _id
  50.         End Get
  51.         Set(ByVal value As Integer)
  52.             _id = value
  53.             NotifyPropertyChanged("Id")
  54.         End Set
  55.     End Property
  56.  
  57.     Private _firstName As String
  58.  
  59.     <Required(ErrorMessage:="First Name is Required.")> _
  60.     <StringLength(15, ErrorMessage:="First Name cannot be greater than 15 characters.")> _
  61.     Public Property FirstName() As String
  62.         Get
  63.             Return _firstName
  64.         End Get
  65.         Set(ByVal value As String)
  66.             _firstName = value
  67.             NotifyPropertyChanged("FirstName")
  68.         End Set
  69.     End Property
  70.  
  71.     Private _lastName As String
  72.  
  73.     <Required(ErrorMessage:="Last Name is Required.")> _
  74.     <StringLength(20, ErrorMessage:="Last Name cannot be greater than 20 characters.")> _
  75.     Public Property LastName() As String
  76.         Get
  77.             Return _lastName
  78.         End Get
  79.         Set(ByVal value As String)
  80.             _lastName = value
  81.             NotifyPropertyChanged("LastName")
  82.         End Set
  83.     End Property
  84.  
  85.     Private _uniqueId As Guid
  86.     Public Property UniqueId() As Guid
  87.         Get
  88.             Return _uniqueId
  89.         End Get
  90.         Set(ByVal value As Guid)
  91.             _uniqueId = value
  92.             NotifyPropertyChanged("UniqueId")
  93.         End Set
  94.     End Property
  95.  
  96.     Private _isActive As Boolean
  97.     Public Property IsActive() As Boolean
  98.         Get
  99.             Return _isActive
  100.         End Get
  101.         Set(ByVal value As Boolean)
  102.             _isActive = value
  103.             NotifyPropertyChanged("IsActive")
  104.         End Set
  105.     End Property
  106.  
  107.     Public Function Clone() As EmployeeModel
  108.         Return New EmployeeModel With { _
  109.         .Id = Id, _
  110.         .FirstName = FirstName, _
  111.         .LastName = LastName, _
  112.         .IsActive = IsActive, _
  113.         .UniqueId = UniqueId}
  114.     End Function
  115.  
  116. End Class


I added validation directly to my model for the First Name and Last Name using Attributes. I also implemented System.ComponentModel.INotifyPropertyChanged to notify my view when a property changes.

In Part 2 of the post I will go through creating a View Model.