Saving Data
It turns out that by combining Framework Entity and MVVM it is very easy to save the data. But there is a small wrinkle...
Although it is perfectly possible to directly wire event handlers to handle events, we know that RoutedCommands are the preferred method for connecting UI events with event handlers. Unfortunately RoutedCommands can only execute code that is the code behind and we would prefer that the event handler be in the ViewModel which already has a reference to the Model. We need to introduce the concept of a RelayCommand.
A RelayCommand implements ICommand but can execute code in the class that defines it. So instead of defining a RoutedCommand in the XAML, we define it in the ViewModel and bind to it. The RelayCommand class is not currently part of WPF so we need to add it to the project ourselves. We only have to do this once. Let's do it now.
1. Add a new class and call it RelayCommand.
2. Replace the default code with this... (credit http://www.dotmaniac.net/)
Public Class RelayCommand
Implements ICommand
Private ReadOnly _CanExecute As Func(Of Boolean)
Private ReadOnly _Execute As Action
Public Sub New(ByVal execute As Action)
Me.New(execute, Nothing)
End Sub
Public Sub New(ByVal execute As Action, ByVal canExecute As Func(Of Boolean))
If execute Is Nothing Then
Throw New ArgumentNullException("execute")
End If
_Execute = execute
_CanExecute = canExecute
End Sub
Public Custom Event CanExecuteChanged As EventHandler Implements System.Windows.Input.ICommand.CanExecuteChanged
AddHandler(ByVal value As EventHandler)
If _CanExecute IsNot Nothing Then
AddHandler CommandManager.RequerySuggested, value
End If
End AddHandler
RemoveHandler(ByVal value As EventHandler)
If _CanExecute IsNot Nothing Then
RemoveHandler CommandManager.RequerySuggested, value
End If
End RemoveHandler
RaiseEvent(ByVal sender As Object, ByVal e As System.EventArgs)
'This is the RaiseEvent block
CommandManager.InvalidateRequerySuggested()
End RaiseEvent
End Event
Public Function CanExecute(ByVal parameter As Object) As Boolean Implements System.Windows.Input.ICommand.CanExecute
If _CanExecute Is Nothing Then
Return True
Else
Return _CanExecute.Invoke
End If
End Function
Public Sub Execute(ByVal parameter As Object) Implements System.Windows.Input.ICommand.Execute
_Execute.Invoke()
End Sub
End Class
3. Add a public property to the ViewModel like this...
Public Property SaveCommand As RelayCommand
4. Now let's add a [Save] button to our XAML. Add another RowDefinition and add this button. Note that its Command is bound to our new RelayCommand.
<Button Grid.Row="1" Grid.Column="1" Content="Save" Command="{Binding Path=SaveCommand}"/>
5. Right now our SaveCommand does nothing. We need to hook it up to an eventhandler in the ViewModel's constructor. Add the following line of code at the end of the constructor...
SaveCommand = New RelayCommand(New Action(AddressOf DoSave))
7. You can now run the application, change the application name, click [Save], kill the application, and rerun it to see the changed application name. Other than the one-time creation of the RelayCommand class, saving the data is very easy.
In the next post in the series we will look at detecting and adding missing data in the ViewModel.
3. Add a public property to the ViewModel like this...
Public Property SaveCommand As RelayCommand
<Button Grid.Row="1" Grid.Column="1" Content="Save" Command="{Binding Path=SaveCommand}"/>
5. Right now our SaveCommand does nothing. We need to hook it up to an eventhandler in the ViewModel's constructor. Add the following line of code at the end of the constructor...
SaveCommand = New RelayCommand(New Action(AddressOf DoSave))
6. Lastly we write the event handler
Public Sub DoSave()
Model.SaveChanges()
End Sub
7. You can now run the application, change the application name, click [Save], kill the application, and rerun it to see the changed application name. Other than the one-time creation of the RelayCommand class, saving the data is very easy.
In the next post in the series we will look at detecting and adding missing data in the ViewModel.
No comments:
Post a Comment