First attempt at implementing MVVM pattern on line-of-business project. I am running into questions that I assume there are eaiser answers for like this one:
Protype window is basic master-detail view of a list of items. (a list of Person objects). The view contains an Infragistics xamDataGrid for the master list. As the item is selected in the grid you can edit the details in the detail panel below and presto, as you tab off the fields in the details panel, the updates are shown “real-time” in the grid data. Only thing is I don’t want “presto”, I want “wait till I press the 'Apply Changes' button”.
I was hoping to avoid creating a separate instance of the list to seperate out the master list from the working set of items that I am adding/deleting/modifying in the details panel.
The path I have gone down:
I overrode the CellValuePresenter Style in the grid field so I can set the binding to “OneWay”. This prevents the real-time update.
<ControlTemplate TargetType="{x:Type igDP:CellValuePresenter}">
<ControlTemplate.Resources>
<Style TargetType="TextBlock">
<Setter Property="Background" Value="{Binding Path=DataItem.NameUIProperty.IsDirty, Converter={StaticResource BooleanBrushConverter}}" />
<Setter Property="IsEnabled" Value="{Binding Path=DataItem.NameUIProperty.IsEditable}" />
</Style>
</ControlTemplate.Resources>
<ContentControl>
<TextBlock Text="{Binding Path=DataItem.Name, Mode=OneTime}" />
</ContentControl>
</ControlTemplate>
Then I add an “ApplyUpdates” command (RelayCommand) to my PersonListViewModel. This raises the “PERSON_ITEM_
UPDATED” message. I am using VB ports of the MVVM Foundation Messenger and RelayCommand classes.
#Region "ApplyUpdates Command"
Private mApplyUpdatesCommand As New RelayCommand(AddressOf ApplyUpdates)
Public ReadOnly Property ApplyUpdatesCommand() As ICommand
Get
Return mApplyUpdatesCommand
End Get
End Property
Private Sub ApplyUpdates()
'the changes are already in the object in the list so we don't have to do anything here except fire off the Applied message
Messages.AppMessenger.NotifyColleagues(Messages.PERSON_ITEM_UPDATED)
End Sub
#End Region
The PersonView registers for the PERSON_ITEM_
UPDATED message and rebinds the grid when the message is received.
'In Loaded Event
'register for window messages we care about
Messages.AppMessenger.Register(Messages.PERSON_ITEM_UPDATED, AddressOf OnPersonItemUpdated)
'EventHandler
Private Sub OnPersonItemUpdated()
PersonGrid.DataSource = Nothing
PersonGrid.DataSource = mViewModel.List
End Sub
So, that works, but it smells wrong. The view seems to have too much logic in it and the ViewModel is not dictating the state of the UI, the view is.
What am I missing? What method would you use to get the ViewModel to delay publishing the changes to the view?
Update: I am now going down the path of creating a custom ViewModel for the grid (readonly, no Propertychanged notifications) and an editable ViewModel for the detail area. Both VMs would wrap the same business objects, but the ReadOnly version would not publish changes. This would leave the VM in control of when the view updates.