如何将GPS观察器移动到App.xaml超类和Dispatch事件到其他页面/类?

时间:2011-04-06 15:03:21

标签: .net silverlight windows-phone-7 bing-maps

我是开发Silverlight / WPF和WP7的新手,但我熟悉使用控制台或Windows窗体开发C#,所以请耐心等待!

我正在尝试使用Silverlight SDK以及Microsoft.Maps.MapControl和System.Device.Location类创建位置感知应用。我遇到的问题是从其他页面访问“观察者”。做这个的最好方式是什么。我想把它放在我的GUI页面类之外,以便在页面之间切换时,你不会检查UI线程上的新位置并进行重复工作。

以下是我认为应该如何完成的概述(将GPS观察者移动到App超类 - >调度员关于事件更改的页面类),有人请指正!这个问题的主要问题是我无法在没有实例化或静态方法的情况下访问Page类(MainPage.xaml和ListView.xaml)。如果我在页面上创建一个静态方法,它是无用的,因为我无论如何都无法与页面交互(例如设置状态栏,该位置已更改或将mapview移动到新位置)。做这个的最好方式是什么?我想只是在App类中设置一个新的静态位置对象并从子类访问它,但这是手动操作..似乎调度程序是这样做的,但有没有办法引用一个页面没有实例

在我使用的Windows窗体应用中 - readonly FormClass form = (FormClass)Application.OpenForms["formname"];

以下是我的代码示例...

App.xaml.cs(App class) - 显然这是整个WP7应用程序的超类,所以我把观察者放在这里。

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
}

更新 - 这就是我按照我需要的方式工作的方式 -

为我的位置创建公共类Loc -

 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));

    }
}

然后我在App.xaml.cs类中将此类实例化为静态对象,以便在应用程序操作期间利用这些信息。

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();

然后在我的应用内部,只要我需要访问位置信息,我就可以使用 -

App.AppLoc.CurLoc或App.AppLoc.LocStatus

2 个答案:

答案 0 :(得分:0)

当位置或状态发生变化时,您可以使用消息传递系统。所有相关页面都可以订阅此类消息。

或者,根据应用程序的结构,您可以集中处理事件并将其应用于其他页面引用的共享视图模型。

答案 1 :(得分:0)

使用PhoneApplicationPage方法OnNavigatedTo()和OnNavigatedFrom()来注册/取消注册位置接收。 Watcher对象可以在您计划的Application类中定义。 单个页面可以使用静态属性Application.Current来访问Application对象。

我认为你有你所需要的一切。

顺便说一句,您不应该需要事件调度,因为GeoCoordinateWatcher在UI线程上下文中传递事件。

侧面评论: 我们(Resco)刚刚发布了我们位置库的更新。也许this article可以让您了解GPS和基于位置的服务可以做些什么。