0

I am new to MVVM and struggling with some concepts, in particular how to pass values between viewmodels and keep them in sync as property values change.

Take the following scenario, where there are three levels of ViewModel.

JobVM - JobItemsVM - ProductListVM

Each VM is exposed as a property of it's parent. The ProductList contains a ClientID property to filter the list of available products by client. The top level job also contains a ClientID property which identifies who the client for the job is.

Now, what I want to do is for the pick list to react to any change in the client of the top level job (i.e. ProductList.ClientID = Job.ClientID).

I am using MVVMLight. Is using messaging an appropriate solution?

Below is some cut-down code of the classes involved which hopefully helps explain how I currently have things. The question is how can I "synchronise" the JobViewModel.CoreDataEntity.ClientID property with the PickList.FilterClientID property, and trigger PickList.LoadList(true) if JobViewModel.CoreDataEntity.ClientID is changed by the user. Or should I be approaching the whole thing differently?

CODE:

This is the business object representing a job, which includes a ClientID property which is the client assigned to the job

Public Class Job

Implements BLL.Base.ICoreDataEntity

Public Property JobID Implements BLL.Base.ICoreDataEntity.RecordID
Public Property ClientID

End Class

This is the primary view model for the job form, used to display and edit a job and its related records.

Public Class JobViewModel

'THIS PROPERTY HOLDS THE JOB BUSINESS OBJECT
Public Property CoreDataEntity As BLL.Base.ICoreDataEntity

'THIS CONTAINS ADDITIONAL VIEWMODELS USED TO MANAGE SUBLISTS (E.G. JOB ITEMS, COMMUNICATIONS)
Public Property SecondaryDataEntities As List(Of SecondaryDataVMHelper)

Public Sub New(recordID As Integer, enableEdit As Boolean)

    'POPULATE THE COREDATAENTITY WITH A JOB FROM THE DATABASE
    CoreDataEntity = New BLL.Jobs.Job(recordID)

    'initialize secondary view models
    Me.SecondaryDataEntities.Add(New SecondaryDataVMHelper(EntityTypes.JobItem))
    Me.SecondaryDataEntities.Add(New SecondaryDataVMHelper(EntityTypes.Communication))

    'pass down selected details from parent record to secondary view models
    'NOTE - I COULD PASS DOWN THE CLIENT ID HERE AS WELL BUT WHAT IF CLIENTID CHANGES AFTER INITIALIZED?
    For Each x As SecondaryDataVMHelper In SecondaryDataEntities
        x.ParentRecordID = CoreDataEntity.RecordID
        x.ParentEntityType = EntityTypes.Job
        x.ParentRecordDescription = CoreDataEntity.ToString()
    Next

End Sub

End Class

This viewmodel is used to manage a "sub list" related to a parent jobs (e.g. line items on a job)

Public Class SecondaryDataVMHelper
'THIS PROPERTY TELLS US WHAT TYPE OF RECORD WE ARE DEALING WITH IN THE SUB LIST
'FOR INSTANCE, JOB ITEMS
Public Property EntityType As EntityTypes

'AN ADDITIONAL VIEWMODEL TO MANAGE A "PICK LIST" WHICH CAN BE USED TO ADD ITEMS
'FOR INSTANCE, A PRODUCT LIST
Public Property PickList As PickListViewModel

Public Sub New(entityType As EntityTypes)

    'SET UP WHAT TYPE OF DATA WE ARE DEALING WITH
    Me.EntityType = entityType

    'INITIALIZE THE APPROPRIATE PICK LIST 
    PickList = New PickListViewModel()

End Sub

End Class

And finally this viewmodel is used to manage a "pick list" displayed to the user

Public Class PickListViewModel

'THE CLIENT TO FILTER THE PICK LIST BY (E.G. ONLY SHOW PRODUCTS RELATING TO THAT CLIENT)
Public Property FilterClientID As Integer

'THIS STORES THE LIST POPULATED FROM THE DATABASE WHICH IS DISPLAYED IN THE UI
Public Property Records As ObservableCollection(Of Product)

'JUST TO TRACK IF THE PICK LIST HAS BEEN LOADED
Public Property IsLoaded As Boolean

Public Sub LoadList(forceReload As Boolean)
    If forceReload = False And IsLoaded Then Exit Sub
    Records = BLL.Products.GetLiveList(FilterClientID) 'LOAD THE DATA, FILTERING BY CLIENT
    IsLoaded = True
End Sub

End Class
Marshal
  • 6,551
  • 13
  • 55
  • 91
Ian Banks
  • 35
  • 6
  • Have a look at this: http://stackoverflow.com/questions/19513555/passing-parameters-between-viewmodels – FKutsche Nov 24 '15 at 14:22
  • Why `ProductList` should contain `ClientID` ? JobVM has `ClientID`, `JobItemsVM` should have corresponding `JobID` and `ProductListVM ` should have corresponding `JobItemID`. Thats proper way to wire things up. – Marshal Nov 24 '15 at 14:24
  • Can you provide some code to help explain the problem? It's difficult to picture your class structure. – Mike Eason Nov 25 '15 at 08:27
  • Mike Eason, I have edited the original post to include code extracts to hopefully explain things better. Thanks in advance. – Ian Banks Nov 25 '15 at 15:13
  • Looking at the code I think I could easily amalgamate PickListViewModel into the SecondaryDataVMHelper viewmodel rather than splitting it into two to simply a little, although the issue of how I synchronise changes to ClientID still remains – Ian Banks Nov 25 '15 at 15:18

0 Answers0