views:

706

answers:

1

I would like to start a collection of MVVM-light (w/ RIA Services) Best Practices. There are a number of items I have found to be helpful best practices or best approaches, but would like to hear from others using the MVVM-light toolkit and see what they have found as well.

Please post your best practices as answers to this question.

+11  A: 

Basic Usage of MVVM-Light

  1. Intialize the DispatcherHelper in the App.cs file's Application_Startup function
  2. Create ViewModels from the BaseClass
  3. Always Create a ViewModelLocator class, which contains all your view models and is Linked in your application Resources
  4. Use RelayCommands to expose Functions to your view
  5. Learn when to use the DispatchHelper.

Clean-Up Ideas:

  1. When appropriate, add to your ViewModel to clear your DomainContext's EntitySet on Cleanup()?
  2. Call your ViewModelLocator's CleanupSomeVM() function to clear viewmodels when they are no longer actively needed in the application.

I would love to hear from others about when/how you use CleanUp functions. As my application grows, I do feel the need to add some cleanup functions to better manage client memory usage.

For Blendability:

  1. Abstract the Service / Query Implementations to an Interface.
  2. Create 2 classes for each Service Implementation classes (1 for Design, 1 for Production)
  3. Within your each ViewModel, implement its own Service Class (use IsInDesignMode) to create Blendable Service implementations as necessary.
  4. Use a Static variable to hold your DomainContext within the Service Implmentation Class.
  5. Add DispatcherHelper.Initialize() in constructor of ViewModels, but only when in Design Mode. Blend does not load App when loading a page, and this works around that.

For Added Business Logic:

  1. Add Business Logic in the Model first, then in the ViewModel.
  2. Use the Model's partial methods to add logic for appropriate change / update events.
  3. Add Read-Only properties (only getter) to provide summary and calculated values on your model.

For Views:

  1. Always Bind the root to the Locator Object.
  2. Try to keep code-behind logic to layout or custom UI logic only. Avoid referencing your ViewModel.

For Collections:

  1. Use CollectionViewSource for collections in your ViewModels, with a source of the DomainContext's EntitySet
  2. Apply all Filtering, Sorting, and Grouping Logic to the CollectionViewSource in your ViewModel.
  3. After ServiceCalls, Call .View.Refresh() on your CollectionViewSource objects as necessary to update the UI.

For ViewModel coordination (Controller Logic)

  1. Use Messages sparingly, too much complexity can be difficult to manage.
  2. Use the NotificationMessage and PropertyChangedMessage classes to Send/Receive with.

For RIA DomainServices:

  1. Implement any logging in the persist changes function, not the update/insert/delete logic.
  2. During Insert,Update,Delete functions, if you need to reference another Entity via Navigation Property, either check the EntityStatus first, or load the entity from another Context, to prevent EntityStatus conflicts.

For Debugging / Testing:

  1. Check the Output Window for Binding Errors and Fix them. Binding Errors fail silently to the user, but degrade application performance and expected behavior.
  2. Create Unit Tests in Silverlight to verify any added Model / Business Logic
  3. Create Unit Test project to test server-side logic and functions

For Entity Framework:

  1. Keep 1-to-1 Match of EntitiesContext to Domain Service. Trying to split this another way causes issues.
  2. Do NOT use the [Composition] attribute unless you fully intend to spend a lot of time carefully building your Insert, Update, and Delete logic.
  3. Use a separate service to serve custom types back to your RIA Client. Do not add them to your DomainService for your EntityFramework Object
  4. Perform Server-side update/integration logic (such as updating other systems) in the PersistChangeSet function, not in the Insert, Update, Delete functions. This will prevent you from accidentally pulling in an entity via Navigation Properties, which will leave your detached version non-updated.
  5. Create an additional Context to find current values during update/integration logic.
Ryan from Denver