2
votes

Noob question probably. I am developing a mvm wp7 app where the map shows pushpins of salons. The database is retrieved from a link.

The problem i am struggling with is that the observable collection data is not being loaded from the App._ViewModel (where the json serializer parses the database and works fine). On debugging the app shows a plain map and thats all. On returning a string attribute from the database causes a break on that code. i tried messagebox as well to show the string, still crashes.

Heres the code:

mainviewmodel.cs

public class MainViewModel {
public bool IsDataLoaded { get; private set; }

    public ObservableCollection<SalonViewModel> SalonCollection { get; private set; }


    public MainViewModel()
    {
        IsDataLoaded = false; 
    }

    public ObservableCollection<SalonViewModel> LoadData()
    {
        SalonCollection = new ObservableCollection<SalonViewModel>();
        var wednesday = new Uri("http://blehbleh.txt");
        WebClient wc = new WebClient();
        wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
        wc.OpenReadAsync(wednesday);

        return SalonCollection;
    }

    public void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
    { 
        try
        { 
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(ObservableCollection<SalonViewModel>));
            ObservableCollection<SalonViewModel> list = serializer.ReadObject(e.Result) as ObservableCollection<SalonViewModel>;

            foreach (SalonViewModel b in list)
            { 
               SalonCollection.Add(new SalonViewModel { sid=b.sid,sname=b.sname,sgeo_lat=b.sgeo_lat,sgeo_lon=b.sgeo_lon, 

            }

            this.IsDataLoaded = true;

        }
        catch (Exception ex)
        {
            //throw ex;
            MessageBox.Show(ex.Message);
        }
    }

The App.cs

public partial class App : Application {

    private static MainViewModel viewModel;

    public static MainViewModel _viewModel
    { 
        get
        {
            if (viewModel == null)
            {
                viewModel = new MainViewModel();
            }

            return viewModel;
        }
    }

    void LoadData()
    {
        if (!_viewModel.IsDataLoaded)
        {
            _viewModel.LoadData();
        }
    }

etc

Heres the mappage.cs

private void salon_map_Loaded (object sender, RoutedEventArgs e) {

             foreach (SalonViewModel Salon in App._viewModel.LoadData)
             {
                 MessageBox.Show(Salon.sname);
                 Pushpin p = new Pushpin();
                 p.Content = Salon.sname + System.Environment.NewLine + "Rate: "; 
                 Layer.AddChild(p, new GeoCoordinate(Salon.sgeo_lon, Salon.sgeo_lat)); 
             }

             Map1.Children.Add(Layer); 

         }
1

1 Answers

1
votes

In your MainViewModel LoadData function, OpenReadAsync() is an asynchronous function, and thus returning SalonCollection on the next line will return an empty ObservableCollection, since the callback function wc_OpenReadCompleted has not run yet.

Also, the reason the MessageBox.Show crashes is because you are attempting to call a UI function on a non-UI thread (solution to that here: Dispatcher.Invoke() on Windows Phone 7?)

Instead of returning the ObservableCollection and manually adding children to the map from that, try binding a MapItemsControl layer of the Map to the ObservableCollection of your view model. There's a decent example of doing that here: Binding Pushpins to Bing Maps in Windows Phone