how to call PositionChanged method manually in windows phone? - windows-phone-7

I have the below event that gets fired upon geocoordinatewatcher object position changed event.
void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
//do the stuff here
}
Now when user clicks on any location on the map I want to call the above method and do the same stuff everytime.
Any idea how do I achieve this ?

Either call your event handler manually:
var position = new GeoPosition<GeoCoordinate>(DateTimeOffset.Now, new GeoCoordinate(32, 64));
this.watcher_PositionChanged(this, new GeoPositionChangedEventArgs<GeoCoordinate>(position));
Or rewrite your event handler to put the logic in another method, then call it:
void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
this.UpdatePosition(e.Position);
}
private void UpdatePosition(GeoCoordinate coordinates)
{
// Do the stuff here
}
This way, you just have to call UpdatePosition whenever you feel like it. I'd recommend this solution, it's way cleaner than the first one.

Related

Xamarin.Forms android app - event handler keeping PageModel referenced despite being unsubscribed

We've got a Xamarin.Forms Android app in which we're displaying progress on a loading page, the progress value being sent by an event from another class.
We're using FreshMvvm which has ViewIsAppearing and ViewIsDisappearing overrides available in the PageModel.
So we're subscribing on ViewIsAppearing, and unsubscribing in ViewIsDisappearing - we're also unsubscribing in a PrepareForDispose method which is intended to ensure the PageModel has cleaned up so that it can be disposed.
Code is below. ProgressManager is supplied by IoC
protected override void ViewIsAppearing (object sender, EventArgs e)
{
base.ViewIsAppearing (sender, e);
ProgressManager.ProgressEvent += ProgressManager_ProgressEvent;
}
protected override void ViewIsDisappearing (object sender, EventArgs e)
{
base.ViewIsDisappearing (sender, e);
RemoveEventHandlers();
}
public override void PrepareForDispose()
{
RemoveEventHandlers();
base.PrepareForDispose();
}
private void RemoveEventHandlers()
{
ProgressManager.ProgressEvent -= ProgressManager_ProgressEvent;
}
The problem is that, when examining object in Profiler, we can see the LoadingPageModel is still in memory, because of the EventArgs created in the ViewIsAppearing (examining the "Paths To Root" in Profiler tells us this).
When I log/debug the app, I can see that RemoveEventHandlers has been called.
So is _ProgressManager.ProgressEvent -= ProgressManager_ProgressEvent;_ failing to remove the handler, or is there another reason that we've still got a reference to the PageModel from the EventArgs?
Edit One possibility is that we're subscribing more than once, but unsubscribing only once. I've checked with debug/logging, and I don't think this is the case. We're subscribing/unsubscribing symmetrically.
It turns out that we were subscribing twice (due to the lifecyle of the page in question at the start of the app lifecycle). Therefore the single unsubscribe was leaving a subscription behind.
Fixing this fixed the problem.

Windows Forms Event before the Closing event? [duplicate]

I have a form that spawns a BackgroundWorker, that should update form's own textbox (on main thread), hence Invoke((Action) (...)); call.
If in HandleClosingEvent I just do bgWorker.CancelAsync() then I get ObjectDisposedException on Invoke(...) call, understandably. But if I sit in HandleClosingEvent and wait for bgWorker to be done, than .Invoke(...) never returns, also understandably.
Any ideas how do I close this app without getting the exception, or the deadlock?
Following are 3 relevant methods of the simple Form1 class:
public Form1() {
InitializeComponent();
Closing += HandleClosingEvent;
this.bgWorker.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {
while (!this.bgWorker.CancellationPending) {
Invoke((Action) (() => { this.textBox1.Text = Environment.TickCount.ToString(); }));
}
}
private void HandleClosingEvent(object sender, CancelEventArgs e) {
this.bgWorker.CancelAsync();
/////// while (this.bgWorker.CancellationPending) {} // deadlock
}
The only deadlock-safe and exception-safe way to do this that I know is to actually cancel the FormClosing event. Set e.Cancel = true if the BGW is still running and set a flag to indicate that the user requested a close. Then check that flag in the BGW's RunWorkerCompleted event handler and call Close() if it is set.
private bool closePending;
protected override void OnFormClosing(FormClosingEventArgs e) {
if (backgroundWorker1.IsBusy) {
closePending = true;
backgroundWorker1.CancelAsync();
e.Cancel = true;
this.Enabled = false; // or this.Hide()
return;
}
base.OnFormClosing(e);
}
void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
if (closePending) this.Close();
closePending = false;
// etc...
}
I've found another way. If you have more backgroundWorkers you can make:
List<Thread> bgWorkersThreads = new List<Thread>();
and in every backgroundWorker's DoWork method make:
bgWorkesThreads.Add(Thread.CurrentThread);
Arter that you can use:
foreach (Thread thread in this.bgWorkersThreads)
{
thread.Abort();
}
I used this in Word Add-in in Control, which i use in CustomTaskPane. If someone close the document or application earlier then all my backgroundWorkes finishes their work, it raises some COM Exception(I don't remember exatly which).CancelAsync() doesn't work.
But with this, I can close all threads which are used by backgroundworkers Immediately in DocumentBeforeClose event and my problem is solved.
Here was my solution (Sorry it's in VB.Net).
When I run the FormClosing event I run BackgroundWorker1.CancelAsync() to set the CancellationPending value to True. Unfortunately, the program never really gets a chance to check the value CancellationPending value to set e.Cancel to true (which as far as I can tell, can only be done in BackgroundWorker1_DoWork).
I didn't remove that line, although it doesn't really seem to make a difference.
I added a line that would set my global variable, bClosingForm, to True. Then I added a line of code in my BackgroundWorker_WorkCompleted to check both e.Cancelled as well as the global variable, bClosingForm, before performing any ending steps.
Using this template, you should be able to close your form out at any time even if the backgroundworker is in the middle of something (which might not be good, but it's bound to happen so it might as well be dealt with). I'm not sure if it's necessary, but you could dispose the Background worker entirely in the Form_Closed event after this all takes place.
Private bClosingForm As Boolean = False
Private Sub SomeFormName_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
bClosingForm = True
BackgroundWorker1.CancelAsync()
End Sub
Private Sub backgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
'Run background tasks:
If BackgroundWorker1.CancellationPending Then
e.Cancel = True
Else
'Background work here
End If
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
If Not bClosingForm Then
If Not e.Cancelled Then
'Completion Work here
End If
End If
End Sub
Can you not wait on the signal in the destructor of the form?
AutoResetEvent workerDone = new AutoResetEvent();
private void HandleClosingEvent(object sender, CancelEventArgs e)
{
this.bgWorker.CancelAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
while (!this.bgWorker.CancellationPending) {
Invoke((Action) (() => { this.textBox1.Text =
Environment.TickCount.ToString(); }));
}
}
private ~Form1()
{
workerDone.WaitOne();
}
void backgroundWorker1_RunWorkerCompleted( Object sender, RunWorkerCompletedEventArgs e )
{
workerDone.Set();
}
Firstly, the ObjectDisposedException is only one possible pitfall here. Running the OP's code has produced the following InvalidOperationException on a substantial number of occasions:
Invoke or BeginInvoke cannot be called
on a control until the window handle
has been created.
I suppose this could be amended by starting the worker on the 'Loaded' callback rather than the constructor, but this entire ordeal can be avoided altogether if BackgroundWorker's Progress reporting mechanism is used. The following works well:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
while (!this.bgWorker.CancellationPending)
{
this.bgWorker.ReportProgress(Environment.TickCount);
Thread.Sleep(1);
}
}
private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.textBox1.Text = e.ProgressPercentage.ToString();
}
I kind of hijacked the percentage parameter but one can use the other overload to pass any parameter.
It is interesting to note that removing the above sleep call clogs the UI, consumes high CPU and continually increases the memory use. I guess it has something to do with the message queue of the GUI being overloaded. However, with the sleep call intact, the CPU usage is virtually 0 and the memory usage seems fine, too. To be prudent, perhaps a higher value than 1 ms should be used? An expert opinion here would be appreciated... Update: It appears that as long as the update isn't too frequent, it should be OK: Link
In any case, I can't foresee a scenario where the updating of the GUI has to be in intervals shorter than a couple of milliseconds (at least, in scenarios where a human is watching the GUI), so I think most of the time progress reporting would be the right choice
I really dont see why DoEvents is regarded as such a bad choice in this case if you are using this.enabled = false. I think it would make it quite neat.
protected override void OnFormClosing(FormClosingEventArgs e) {
this.Enabled = false; // or this.Hide()
e.Cancel = true;
backgroundWorker1.CancelAsync();
while (backgroundWorker1.IsBusy) {
Application.DoEvents();
}
e.cancel = false;
base.OnFormClosing(e);
}
Your backgroundworker should not use Invoke to update the textbox. It should ask the UI thread nicely to update the textbox using event ProgressChanged with the value to put in the textbox attached.
During event Closed (or maybe event Closing), the UI thread remembers that the form is closed before it cancels the backgroundworker.
Upon receiving the progressChanged the UI thread checks if the form is closed and only if not, it updates the textbox.
This won't work for everyone, but if you are doing something in a BackgroundWorker periodically, like every second or every 10 seconds, (perhaps polling a server) this seems to work well to stop the process in an orderly manner and without error messages (at least so far) and is easy to follow;
public void StopPoll()
{
MyBackgroundWorker.CancelAsync(); //Cancel background worker
AutoResetEvent1.Set(); //Release delay so cancellation occurs soon
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
while (!MyBackgroundWorker.CancellationPending)
{
//Do some background stuff
MyBackgroundWorker.ReportProgress(0, (object)SomeData);
AutoResetEvent1.WaitOne(10000);
}
}
I'd pass in the SynchronizationContext associated with the textbox to the BackgroundWorker and use that to perform Updates on the UI thread. Using SynchronizationContext.Post, you can check if the control is disposed or disposing.
What about Me.IsHandleCreated?
Private Sub BwDownload_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BwDownload.RunWorkerCompleted
If Me.IsHandleCreated Then
'Form is still open, so proceed
End If
End Sub
Another way:
if (backgroundWorker.IsBusy)
{
backgroundWorker.CancelAsync();
while (backgroundWorker.IsBusy)
{
Application.DoEvents();
}
}
One solution that works, but too complicated. The idea is to spawn the timer that will keep trying to close the form, and form will refuse to close until said bgWorker is dead.
private void HandleClosingEvent(object sender, CancelEventArgs e) {
if (!this.bgWorker.IsBusy) {
// bgWorker is dead, let Closing event proceed.
e.Cancel = false;
return;
}
if (!this.bgWorker.CancellationPending) {
// it is first call to Closing, cancel the bgWorker.
this.bgWorker.CancelAsync();
this.timer1.Enabled = true;
}
// either this is first attempt to close the form, or bgWorker isn't dead.
e.Cancel = true;
}
private void timer1_Tick(object sender, EventArgs e) {
Trace.WriteLine("Trying to close...");
Close();
}

Manipulation_started doesn't work on a map

Hi to all I'm trying to set a listener for the ManipulationStarted, ManipulationDelta, ManipulationCompleted of a map to detect if the user drag a map around, but looks like none of those events are launched if I drag the map. If I set a tap listener for the map ManipulationStarted is correctly launched.
What I'm doing wrong?
xaml code:
<Controls:Map x:Name="myMap"
Grid.Row="0"
Loaded="myMap_Loaded"
ManipulationDelta="myMap_ManipulationDelta"
ManipulationCompleted="myMap_ManipulationCompleted"
ManipulationStarted="myMap_ManipulationStarted"
Tap="myMap_Tap">
code behind:
private void myMap_ManipulationDelta(object sender, System.Windows.Input.ManipulationDeltaEventArgs e)
{
Debug.WriteLine("Event:: MyMap_manipulationdelta");
}
private void myMap_ManipulationCompleted(object sender, System.Windows.Input.ManipulationCompletedEventArgs e)
{
Debug.WriteLine("Event:: MyMap_manipulationcompleted");
}
private void myMap_ManipulationStarted(object sender, System.Windows.Input.ManipulationStartedEventArgs e)
{
Debug.WriteLine("Event:: MyMap_manipulationstarted");
}
private void myMap_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
Debug.WriteLine("Event:: MyMap_tap");
}
I'm on a normal page, no pivot or panorama.
I'm afraid that you won't be able to handle those events because Map control intercepts them. Although there is a property UseOptimizedManipulationRouting, but as I've tested it - it doesn't help much in this situation.
I dont't know what you are trying to achieve, but if you don't need ManipulationDeltaEventArgs then maybe you consider using different events such as: MouseEnter, ResolveCompleted and CenterChanged.
If you need them then as JustinAngel suggested here you can follow these instructions and use Touch.FrameReported event for your purpose.
EDIT - code sample
If I've understood you properly, you would like to know when the User touches the Map, MouseEnter won't be the best choice as it will work only first time, then if mouse didn't leave the Map (user touched somewhere else), it won't fire again. Better solution here (following instructions above) can be such a code:
public MainPage()
{
InitializeComponent();
Touch.FrameReported += Touch_FrameReported;
}
private void Touch_FrameReported(object sender, TouchFrameEventArgs e)
{
TouchPoint point = e.GetPrimaryTouchPoint(myMap);
if (point.Action == TouchAction.Move && point.Position.Y > 0)
{
MessageBox.Show("User is Moving Finger over the Map!");
}
}

WP7 How to write a function: binding data method will be called every 10s?

Could you show me the way or the idea how to execute biding data every 10s??
Let's see the code below:
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
proxy.DanhSachPhongChoiCompleted += new
EventHandler<DanhSachPhongChoiCompletedEventArgs>(proxy_DanhSachPhongChoiCompleted);
proxy.DanhSachPhongChoiAsync();
}
void proxy_DanhSachPhongChoiCompleted(object sender, DanhSachPhongChoiCompletedEventArgs e)
{
Room[] table = e.Result;
listDSPhong.ItemsSource = e.Result;
}
We can see: ater my page loaded, the binding data will execute ONLY ONE TIME. I need to call 2 methods below every 10s. How should I do? Thanks for teaching me!
proxy.DanhSachPhongChoiCompleted += new
EventHandler<DanhSachPhongChoiCompletedEventArgs>(proxy_DanhSachPhongChoiCompleted);
proxy.DanhSachPhongChoiAsync();
You can use e.g. DispatcherTimer class.
Here's the sample:
https://stackoverflow.com/a/3266071/126995
You better start your timer in NavigatedTo, and kill it in NavigatedFrom.
P.S. I suspect there's a memory leak in your code. Please read this.
you can use Microsoft's reactive library
http://msdn.microsoft.com/en-us/data/gg577609.aspx
and do something like this :
public void callfunction()
{
IScheduler scheduler = NewThreadScheduler.Default;
scheduler.Schedule(TimeSpan.FromSeconds(5), new Action<Action<TimeSpan>>(myRepeatingFunction));
}
private void myRepeatingFunction(Action<TimeSpan> action)
{
//process here
action(TimeSpan.FromSeconds(5)); // five second interval
}

PhotoChooserTask.Completed not fired

I'm trying to using PhotoChooserTask for our purposes.
After calling photoChooserTask.Show() chooser is showed but when I choose a picture it's closing and event Completed not fired !
Why?
And more, after that PhotoChooserTask not showed next time when calling Show.
P.S. if i try this code in new solution - it will work fine, but why it doesn't work in our project?
PhotoChooserTask photoChooserTask;
private void button2_Click(object sender, System.Windows.RoutedEventArgs e)
{
photoChooserTask = new PhotoChooserTask();
photoChooserTask.Completed += new EventHandler<PhotoResult>(photoChooserTask_Completed);
photoChooserTask.Show();
// TODO: Add event handler implementation here.
}
void photoChooserTask_Completed(object sender, PhotoResult e)
{
//Bla bla bla
}
I solved this problem.
So, project CAN NOT have more than one photo chooser.
You can't declare PhotoChooserTask in Page1 and Page2 with different logic of processing.
Hope this will helpfull for someone.
You should make sure that you respect the guidelines for creating and initializing the object:
To ensure that your application receives the result of the
PhotoChooserTask, the object must be declared with class scope
within the PhoneApplicationPage class and you must call the chooser
constructor and assign the Completed event delegate within the page’s
constructor.
Source

Resources