Select to view content in your preferred language

Silverilght MVVM Binding Maps

592
2
11-04-2011 10:17 AM
SamRosewall
Emerging Contributor
Hi,
I am fairly new to using ArcGIS mapping in Silverlight and am having a few issues that I'm hoping someone can help point me in the right direction.

Problem 1. I have been struggling like crazy to get binding to work with anything in the esri:Map. I tried binding the Layers like so

<esri:Map x:Name="MyMap" Layers="{Binding VisibleLayers}" />


Then in my ViewModel I have


        public ObservableCollection<Layer> VisibleLayers
        {
            get 
            {
                if(_visibleLayers == null)
                    _visibleLayers = new ObservableCollection<Layer>();
                return _visibleLayers; 
            }
            set { _visibleLayers = value; OnPropertyChanged("VisibleLayers"); }
        }


It is not a DataContext problem because I have several text boxes and labels binding just fine to the same viewModel. So in the ViewModel's Constructor I have the following:

ArcGISTiledMapServiceLayer arcgisLayer = new ArcGISTiledMapServiceLayer();
            arcgisLayer.Url = "http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer";
            VisibleLayers.Add(arcgisLayer);


Now if I just put this Layer int he XAML it works fine, but that is not my goal. I have 15 or more layers that I need to have the ability to add to VisibleLayers on Demand and I don't want this all done in the code behind. Any Suggestions would be GREATLY Appreciated?


Problem 2: I have tried 5 or 6 different means to maintain the Map Extents and selected Graphics through Binding, but am failing miserable. It appears that in the code behind I can create an Envelope and assign the Map's extent to the envelope. However, if I do:

<esri:Map x:Name="MyMap" Extent="{Binding MapEnvelope}" />


and in viewModel I have

        public Envelope MapEnvelope
        {
            get { return _mapEnvelope; }
            set { _mapEnvelope = value; OnPropertyChanged("MapEnvelope"); }
        }


However, I always get an error on InitilizeComponents because of the MapExtent binding. I have also tried setting the return value to _mapEnvelope.Extent, but that didn't work either. I have tried creating a converter like so:

<esri:Map x:Name="MyMap" Extent="{Binding MapEnvelope, Conveter={StaticResource EnvelopeToExtentConverter}" />


and then in my converter class I have:

namespace MyNamespace.Converters
{
    public class EnvelopeToExtentsConverter<T> : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value != null)
                return (((Envelope)value).XMin + "," + ((Envelope)value).XMax + "," + ((Envelope)value).YMin + "," + ((Envelope)value).YMax);
            else
                return null;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;  // fix later if get works
        }
    }

    public class MapToExtentsConverter : EnvelopeToExtentsConverter<Envelope> { }
}


and this still gives the same error, I never even get into the converter with a break point so it isn't getting this far. I have also tried this:

     
  <esri:Map x:Name="MyMap" >
            <esri:Map.Extent>
                <esri:Envelope XMax="{Binding MapExtentXMin}" XMin="{Binding MapExtentXMax}" YMax="{Binding MapExtentYMin}" YMin="{Binding MapExtentYMax}" />
            </esri:Map.Extent>
</esri:Map>


and in the viewModel had a double for everyone of these properties and that didn't work either.


I have also tried binding to a String in the viewModel to maintain the extents and am suffering to a losing battle. I finally ending up cheating by firing a generic EventArgs<myMap> to the viewModel that listens, grabs the map, creates a duplicate in the viewModel. Then on MapLoad I fire it again to the viewModel to recieve it's Map Attributes from the duplicate. This is sloppy and not the correct way to do it. I'm making a wizard that they can come to and from this map page and change selections and I don't want a fresh map everytime they get here, and I DO NOT want to keep views alive after I have left it.

Any suggestions???


Thanks very much for any feedback.


Sam
0 Kudos
2 Replies
JenniferNery
Esri Regular Contributor
Extent is not a DependencyProperty and therefore does not support binding. Layers is a DependencyProperty and can support binding, however it is of type LayerCollection.
0 Kudos
SamRosewall
Emerging Contributor
Thanks Jennifer, that did work. I can now add my layers in the viewModel and bind to them. Any ideas on how to save the Extents of the Map in the viewModel without passing the Map to the ViewModel? I am creating a duplicate Map in my ViewModel and setting it's extents equal to the UI's passed Map and then when the View comes back since I don't destroy the ViewModel, I just pass the UI's Map again and set it's extents equal to the duplicate Map's Extents.

I would like to avoid passing the UI Map to the ViewModel if at all possible.

Thanks again, that was a lot of help already,

Sam
0 Kudos