How do I move GPS watcher to App.xaml superclass and Dispatch events to other pages/classes?

 ̄綄美尐妖づ 提交于 2020-02-01 06:35:38

问题


I am new to developing for silverlight/WPF and WP7, however I am familiar with developing C# using console or windows form, so bear with me!

I am trying to create a location aware app using the Silverlight SDK and the Microsoft.Maps.MapControl and the System.Device.Location classes. The problem I am having is accessing the "watcher" from other pages. What is the best way to do this. I want to put it outside of my GUI page classes so that when switching between pages, you are not checking for a new location on the UI thread and doing duplicate work..

Here is an outline of how I think it should be done (moving GPS watcher to App superclass -> Dispatcher to page classes on event change), somebody please correct me! The main problem with this is I cannot access the Page classes (MainPage.xaml and ListView.xaml) without instantiation or static methods. If I make a static method on the pages, it is useless because I cannot interact with the page anyway (such as setting a status bar that location changed or move the mapview to the new location). What is the best way to do this? I have thought just setting a new static location object in the App class and access that from the sub classes but this is manual operation.. It seems that the dispatcher is the way to do it, but is there a way to reference a page without instantiation?

In Windows Forms apps I use - readonly FormClass form = (FormClass)Application.OpenForms["formname"];

Here is an example of my code...

App.xaml.cs (App class)- Apparently this is the super class for the entire WP7 app so I put my watcher here.

Public Partial Class App : Application
{
Private IGeoPositionWatcher<GeoCoordinate> _watcher;
    Public App()
   {
     //App constructor
      //Mock GPS services on WP7 emulator
            if (_watcher == null)
            {
                var events = new[] {
                    new  GeoCoordinateEventMock { Latitude=33.43, Longitude=-112.02, Time=new TimeSpan(0,0,1) },
                   };
                _watcher = new EventListGeoLocationMock(events);
            }
            //add event handlers for statuschanged and positionchanged
            _watcher.StatusChanged += WatcherStatusChanged;
            _watcher.PositionChanged += WatcherPositionChanged;
            //start watcher
            _watcher.Start();
    }
#event handlers
       public void WatcherStatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() => MainPage.MyStatusChanged(e));
          Deployment.Current.Dispatcher.BeginInvoke(() => OtherPage.MyStatusChanged(e));
        }
        public void WatcherPositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() => MainPage.MyPositionChanged(e));
           Deployment.Current.Dispatcher.BeginInvoke(() => OtherPage.MyPositionChanged(e));
        }

}

MainPage.xaml.cs (MainPage class)-
public void MyPositionChanged(GeoPositionChangedEventArgs<GeoCoordinate> e)
{
//do some stuff
}
public void MyStatusChanged(GeoPositionStatusChangedEventArgs e)
{
//do some stuff
}

Updated- This is how I got it working the way I needed-

Created a public class Loc for my location-

 public class Loc
{

    private readonly GeoCoordinateWatcher _watcher;
    public Location CurLoc { get; set; }
    public string LocStatus { get; set; }

   public Loc()
    {
        if (_watcher != null) return;
        //---get the default accuracy-

        _watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.Default)


                      {
                          MovementThreshold = 1000
                      };


        //add event handlers for statuschanged and positionchanged
        _watcher.StatusChanged += WatcherStatusChanged;
        _watcher.PositionChanged += WatcherPositionChanged;

        //start watcher
        _watcher.Start();
    }

   private void MyPositionChanged(GeoPositionChangedEventArgs<GeoCoordinate> e)
    {
        //called from the _watcher Position changed eventHandler

            CurLoc = new Location(e.Position.Location.Latitude, e.Position.Location.Longitude);



    }

    private void MyStatusChanged(GeoPositionStatusChangedEventArgs e)
    {
        //called from the _watcher position status changed event handler

        switch (e.Status)
        {
            case GeoPositionStatus.Disabled:
                LocStatus = "Location services disabled!";

                break;
            case GeoPositionStatus.Initializing:
                LocStatus = "Finding current location...";

                break;
            case GeoPositionStatus.NoData:
                LocStatus = "No location data available...";

                break;
            case GeoPositionStatus.Ready:
                LocStatus = "Found you";

                break;
        }
    }

    private  void WatcherStatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
    {
        Deployment.Current.Dispatcher.BeginInvoke(() => MyStatusChanged(e));
    }

    private void WatcherPositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
    {
        Deployment.Current.Dispatcher.BeginInvoke(() => MyPositionChanged(e));

    }
}

Then I instantiate this class in my App.xaml.cs class as a static object so I can utilize the information during the app operation.

public partial class App 
{
    /// <summary>
    /// Provides easy access to the root frame of the Phone Application.
    /// </summary>
    /// <returns>The root frame of the Phone Application.</returns>
    public PhoneApplicationFrame RootFrame { get; private set; }

           public static Loc AppLoc = new Loc();

Then inside my app whenever I need to access location information I can just use-

App.AppLoc.CurLoc or App.AppLoc.LocStatus


回答1:


Use PhoneApplicationPage methods OnNavigatedTo() and OnNavigatedFrom() to register/unregister position receiving. Watcher object may be defined in the Application class as you plan. Individual pages can use static property Application.Current to access Application object.

I think you have all you need.

BTW, you should not need event dispatching as the GeoCoordinateWatcher delivers events in the UI thread context.

A side remark: We (Resco) just published an update to our Location library. Maybe this article could give you some idea what can be done with GPS and location-based services.




回答2:


You could use a messaging system when the position or status changes. All relevant pages could subscribe to such messages.

Alternatively, depending on the structure of your app, you could have the events handled centrally and applied to a shared viewmodel which is referred to by the other pages.



来源:https://stackoverflow.com/questions/5568581/how-do-i-move-gps-watcher-to-app-xaml-superclass-and-dispatch-events-to-other-pa

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!