Results 1 to 6 of 6

Thread: Update main page when a Gelocator Position change event fires

  1. #1

    Thread Starter
    New Member
    Join Date
    Jan 2017
    Posts
    14

    Update main page when a Gelocator Position change event fires

    Hallo guys,

    I'm tring to write a simple mapping WPF app that use the Geolocator class to retreive the current position.

    Code is simple:

    Imports Windows.Devices.Geolocation 'Geolocation Namespace
    Imports System.Threading 'Threading Namespace

    Public NotInheritable Class MainPage


    Inherits Page

    Private WithEvents glGeo As New Geolocator 'Create New Geolocator Object With Its Associated Events

    Private Async Sub btGetLocation_Click(sender As Object, e As RoutedEventArgs) Handles btGetLocation.Click
    Try
    ' Find Position
    Dim gpPos As Geoposition = Await glGeo.GetGeopositionAsync()

    'Display Coordinates
    tbLatitude.Text = gpPos.Coordinate.Point.Position.Latitude.ToString()
    tbLongitude.Text = gpPos.Coordinate.Point.Position.Longitude.ToString()

    Catch err As Exception

    End Try
    End Sub

    This code show the current position when the tbGetPosition button is clicked.

    But I want a continuous update so I've added the following code:


    Private Sub glGeo_PositionChanged(sender As Geolocator, args As PositionChangedEventArgs) Handles glGeo.PositionChanged

    Dim gpPos As Geoposition = Await glGeo.GetGeopositionAsync()

    'Display Coordinates
    tbLatitude.Text = gpPos.Coordinate.Point.Position.Latitude.ToString()
    tbLongitude.Text = gpPos.Coordinate.Point.Position.Longitude.ToString()

    End Sub


    This code generate an exception in runtime because the tbLatitude and tbLongitude are not accessible form the PositionChanged thread.


    Any suggestion on how to fix it ?

    Thanks, Stefano

  2. #2
    Still learning kebo's Avatar
    Join Date
    Apr 2004
    Location
    Gardnerville,nv
    Posts
    3,757

    Re: Update main page when a Gelocator Position change event fires

    In vb.net you would would do something along these lines...
    Code:
    me.invoke(Sub() tbLatitude.Text = gpPos.Coordinate.Point.Position.Latitude.ToString())
    me.invoke(Sub() tbLongitude.Text = gpPos.Coordinate.Point.Position.Longitude.ToString())
    or it might be more efficient to create a method that sets them both, then invoke that method...

    Code:
    Private Sub setLatLong
        tbLatitude.Text = gpPos.Coordinate.Point.Position.Latitude.ToString()
        tbLongitude.Text = gpPos.Coordinate.Point.Position.Longitude.ToString()
    End sub
    .
    .
    .
    Me.Invoke(Sub() setLatLong)
    (I think thatwould work. maybe not...it's by memory)
    Although since this is wpf, all bets are off
    Process control doesn't give you good quality, it gives you consistent quality.
    Good quality comes from consistently doing the right things.

    Vague general questions have vague general answers.
    A $100 donation is required for me to help you if you PM me asking for help. Instructions for donating to one of our local charities will be provided.

    ______________________________
    Last edited by kebo : Now. Reason: superfluous typo's

  3. #3

    Thread Starter
    New Member
    Join Date
    Jan 2017
    Posts
    14

    Re: Update main page when a Gelocator Position change event fires

    Quote Originally Posted by kebo View Post
    Me.Invoke(Sub() setLatLong)[/CODE](I think thatwould work. maybe not...it's by memory)
    Although since this is wpf, all bets are off
    Thanks Kebo.

    Unfortunately invoke seem not to be a member of the main_page class in the WPF.

    Any other idea ?

  4. #4
    Still learning kebo's Avatar
    Join Date
    Apr 2004
    Location
    Gardnerville,nv
    Posts
    3,757

    Re: Update main page when a Gelocator Position change event fires

    You'll have to check in the WPF forum. I've asked the mods to move your thread.
    Process control doesn't give you good quality, it gives you consistent quality.
    Good quality comes from consistently doing the right things.

    Vague general questions have vague general answers.
    A $100 donation is required for me to help you if you PM me asking for help. Instructions for donating to one of our local charities will be provided.

    ______________________________
    Last edited by kebo : Now. Reason: superfluous typo's

  5. #5
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,988

    Re: Update main page when a Gelocator Position change event fires

    I don't know WPF well enough to know what a WPF-specific version of what Kebo suggested would be, but the problem is right: Only the UI thread can access UI elements.

    So, the problem is that you are accessing UI elements from a background thread, but do you really need to do so? One alternative approach would be to put the information into a pair of variables and raise an event on the UI thread via the SynchronizationContext. I don't actually know whether or not that's a WPF thing, either, but I would expect that it would be. You'd store the current context when you are in the UI thread (store it one time, it's just a context), then from a background thread, you can use that stored context to .Post a call, which will be run on the thread for the context, which would be the UI thread, in this case.

    That may be overly complicated for this, but you ARE talking about geolocation data. If the ONLY thing you are doing with that data is showing it in the labels, then messing around with the SynchronizationContext, simple though it is, may be more work than it is worth. However, if you want to do anything else with that data, you'd want to keep it as numbers rather than keeping it as strings in labels, in which case this approach would be worth it.
    My usual boring signature: Nothing

  6. #6

    Thread Starter
    New Member
    Join Date
    Jan 2017
    Posts
    14

    Re: Update main page when a Gelocator Position change event fires

    Thanks Shaggy Hiker. The SynchronizationContext is the solution

    No need to use variable to store data. The real point is to fire the sub when new data are available (PositionChanged event).

    here is the working code. Very simple and cleaver:

    Public NotInheritable Class MainPage

    Inherits Page

    Private context As SynchronizationContext = SynchronizationContext.Current
    Private WithEvents glGeo As New Geolocator 'Create New Geolocator Object With Its Associated Events
    Private ctsCancel As CancellationTokenSource 'Cancel The Spawned Thread


    Private Sub glGeo_PositionChanged(sender As Geolocator, args As PositionChangedEventArgs) Handles glGeo.PositionChanged

    Me.context.Post(AddressOf update_data, Nothing)

    End Sub


    Private Async Sub update_data()
    Try
    ctsCancel = New CancellationTokenSource()
    Dim canToken As CancellationToken = ctsCancel.Token

    ' Find Position
    Dim gpPos As Geoposition = Await glGeo.GetGeopositionAsync().AsTask(canToken)

    'Display Coordinates
    tbLatitude.Text = gpPos.Coordinate.Point.Position.Latitude.ToString()
    tbLongitude.Text = gpPos.Coordinate.Point.Position.Longitude.ToString()

    Catch err As Exception

    End Try

    End Sub

    End class

    Thanks, Stefano

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width