Why not put MapView into a ViewModel and bind it to a ContentControl? (MVVM)

6509
4
07-24-2015 03:07 PM
KennethLathan
New Contributor II

Hi all,

I've been working on understanding the new .NET api and how it works with MVVM. (I previously worked with the WPF api and my team used MVVM with no problems.) I'm trying to understand why the MapView was split from the Map and how I should route events to the ViewModel. So far I have 3 approaches I've been looking at:

1. Do all event handling in code behind. (Ugg.) Use an event messenger to communicate with the ViewModel if it can't be avoided.

2. Use a Map Controller pattern, as outlined in this post: [blogpost] Navigating the MapView from a ViewModel​ Do all work in the ViewModel, no code behind.

3. Create my Map and MapView in the ViewModel, bind a ContentControl in the View to display the MapView. Do all work in the ViewModel, no code behind.

I am leaning towards #3... it worked for my team in the WPF runtime when we just had a single Map control. #2 seems like a lot of code for what it does. Does anyone know if there are any problems with the third approach? I know it's a little fishy to instantiate a UI element in a ViewModel, but I feel like that is less fishy than creating an elaborate dependency property Map Controller.

Thanks!

Tags (3)
0 Kudos
4 Replies
nakulmanocha
Esri Regular Contributor

You could do that. It all depends how big your application is and how much future enhancements you are looking to make. My suggestion would be keep the MapView within the View and then bind the Map property with the ViewModel as explained here and handle the events from ViewModel instead of code behind. This is good example of MVVM pattern.

Use the MVVM design pattern—ArcGIS Runtime SDK for .NET | ArcGIS for Developers

0 Kudos
KennethLathan
New Contributor II

Nakul,

Thanks for your reply. I am familiar with sending events from the View to the ViewModel. I should have been more specific. I need to send information back to the View. For example:

1. User sends a geospatial query from my UI to the ViewModel.

2. ViewModel sends the query through the Model.

3. Model returns with the results. ViewModel adds them to the Map as a layer.

4,. View zooms to the results I just added.

This seems like it should be something simple to do, but unless you break MVVM you need to create an attached behavior, use an event bus, or stick the MapView into the ViewModel in order for the ViewModel to tell the MapView the extent to zoom to. That's really what my question is about. Which is the best method and why. And if I go with the last method, is there something that will break later.

Thanks,

-Ken

0 Kudos
MarkCederholm
Occasional Contributor III

In my opinion, creating a UI element within a view model is a violation of MVVM.  However, I also feel that way about using a handle to a UI element to perform an operation, which is exactly what the tutorial example does.  The example could be fixed specifically by passing the extent as the command parameter, but the fact is that the MapView is not very MVVM friendly in the first place: ideally, properties like extent and scale should be bindable to the view model bidirectionally.

I have an application that loads different layouts based on a given configuration.  I don't include MapViews in the layouts, because I don't like the dependency on Runtime.  So yes, I search the layout for a designated MapView container, create a MapView, and wire it up inside the view model code, which I shouldn't be doing if I want a pure MVVM design*.  I'm not happy about it, but I haven't found another approach that I like any better.

*After thinking about it some more, I decided to segregate the code better.  Now the app is in three basic components:  1) loader (loads the layout and creates the MapView), 2) view model (just a view model, nothing more), and 3) behavior (handles all interaction with the MapView).

MarkCederholm
Occasional Contributor III

Attached is a simple example of the approach I'm taking.  I definitely think that Behaviors are a great way to make the MapView more MVVM friendly.