PhotoChooserTask + Navigation - windows-phone-7

I taken two Images & added event (MouseButtonDown) for them.
When first image handles event to open Gallery. Second image handles events for open camera.
When user has choosed his image from the gallery, I want to navigate to next page. Its navigates. But before completing navigation process, it displays MainPage & then moves toward next page. I didnt want to display the MainPage once user chooses the image from the gallery.
Plz help.
Thanks in advance.
public partial class MainPage : PhoneApplicationPage
{
PhotoChooserTask objPhotoChooser;
CameraCaptureTask cameraCaptureTask;
// Constructor
public MainPage()
{
InitializeComponent();
objPhotoChooser = new PhotoChooserTask();
objPhotoChooser.Completed += new EventHandler<PhotoResult>(objPhotoChooser_Completed);
cameraCaptureTask = new CameraCaptureTask();
cameraCaptureTask.Completed += new EventHandler<PhotoResult>(objCameraCapture_Completed);
}
void objPhotoChooser_Completed(object sender, PhotoResult e)
{
if (e != null && e.TaskResult == TaskResult.OK)
{
//Take JPEG stream and decode into a WriteableBitmap object
App.CapturedImage = PictureDecoder.DecodeJpeg(e.ChosenPhoto);
//Delay navigation until the first navigated event
NavigationService.Navigated += new NavigatedEventHandler(navigateCompleted);
}
}
void navigateCompleted(object sender, EventArgs e)
{
//Do the delayed navigation from the main page
this.NavigationService.Navigate(new Uri("/ImageViewer.xaml", UriKind.RelativeOrAbsolute));
NavigationService.Navigated -= new NavigatedEventHandler(navigateCompleted);
}
void objCameraCapture_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
//Take JPEG stream and decode into a WriteableBitmap object
App.CapturedImage = PictureDecoder.DecodeJpeg(e.ChosenPhoto);
//Delay navigation until the first navigated event
NavigationService.Navigated += new NavigatedEventHandler(navigateCompleted);
}
}
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;
}
private void image1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
objPhotoChooser.Show();
}
private void image2_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
cameraCaptureTask.Show();
}

To my knowledge when you use one of the choosers, like the Photo gallery or the camera, when your application is activating it will take it back to the page you left it. I don't think there is a way to get around this itself. What you would have to do is catch the Activating event in your main page code and Navigate to the desired page from there.
Now I am not completely sure how you would pass the image from the MainPage to the target page. It does not look like there is a property in the Navigation service to store this value. But you could either set it in an application wide variable, ModelView or even store it in the Isolated Storage area.

You could work around this by navigating to an intermediate blank page and have that intermediate page launch the tasks. When the tasks are completed you can then navigate as normal to your new page and only this blank page will show in transit.

Chris is correct that some of the tasks will navigate away from your app (effectively tombstoning it) and will the re-activate your application when the user returns from the task. For the camera this is particularly difficult, as to my knowledge there is no simple way to detect when you are returning from the camera. Also the camera doesn't work when attached to the debugger or Zune software (at least this is true on my HTC Surround), which makes troubleshooting quite difficult!
In my WP7 Barcode Scanning application I ended up using flags on the PhoneApplicationService class to help track where the navigation events are coming from. Something like:
PhoneApplicationService.Current.State["ReturnFromSampleChooser"] = true;
You can then check for these flags in the PhoneApplicationPage_Loaded or OnNavigatedTo method of your main page and redirect to the desired page as needed. Just make sure to clear the flag and be careful to not cause any loops in the navigation, as that might make your app fail certification (back button must ALWAYS work correctly).
For an example of how to use the camera and set/clear flags using PhoneApplicationService check out the source code for the Silverlight ZXing Barcode Library. You can download the full source here or browse the files online.

Related

How to make Xamarin bubble up gestures

I'm currently in the process of developing a SideDrawer for Xamarin.Forms, because at this point, the one from telerik is rather awful sideeffect-wise.
I know how to do this in WPF, since it's rather easy, but in Xamarin it's way different.
My code for the GestureFrame is pretty much the same as this.
I've used the sources at some github project/xamarin docs/XLabs to get started. At first it was going well, but as soon as i'm placing controls within the gestureframe i will not receive any events anymore, because the childcontrols appear to consume any touch/gesture events there are.
Does this ring a bell to anyone? Right now i'm not sure what i might be doing wrong for the control to behave this way
The Only Gestures that Xamarin Forms handles currently are Tap and DoubleTap these bubble up by default. For Android, Windows and presumably IOS each handle other gestures differently.
Quick Review of Event Handling in the Xamarin.Forms world:
On Android
Gestures are handled by the Renderer each renderer has a Touch event. Touch is raised in the renderer when a gesture occurs. By subscribing to the Touch event and intupreting the EventArgs you can determine what is happening on the screen. Now you could make all the determinations yourself of what the user is doing or use the Mono.Android.GestureDetector to make those decisions for you. GestureDetector requires a GestureListener which it notifies when it believes an event like a tap or double have occured. Your Gesture listener can then contain whatever code you want to respond to these events.
On Windows
Each native control determines for itself When an event has occurred and exposes a set of EventHandlers for those events. To respond to these events you create a custom renderer and subscribe to the events on the native controls that then execute your own code.
On IOS?
Don't know yet haven't got that far in my project https://github.com/Indiponics/IndiXam-Lib maybe someone else can give you that piece.
Bubbling up the Events
Lets look at a simple bubbling situation:
public class App : Application
{
public App()
{
// The root page of your application
MainPage = new ContentPage
{
Content = new Frame
{
Content =
new Label {
Text = "Hold Me, Thrill Me, Kiss Me"
}
}
};
}
}
Lets put some Custom Renderers together and look at whats happening. To start with we'll need a renderer for every control in the stack so in our case a Label Renderer and a Frame Renderer.
We'll Start with Windows:
[assembly: ExportRenderer(typeof(Label), typeof(myLabelCustomRenderer))]
[assembly: ExportRenderer(typeof(Frame), typeof(myFrameCustomRenderer))]
namespace App4.WinPhone
{
public class myFrameCustomRenderer:FrameRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Frame> e)
{
base.OnElementChanged(e);
if(e.NewElement!=null)
{
this.Control.Hold += Control_Hold;
}
}
void Control_Hold(object sender, System.Windows.Input.GestureEventArgs e)
{
System.Diagnostics.Debug.WriteLine("Frame Held");
e.Handled = false;
}
}
public class myLabelCustomRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Label> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
this.Control.Hold += Control_Hold;
}
}
void Control_Hold(object sender, System.Windows.Input.GestureEventArgs e)
{
System.Diagnostics.Debug.WriteLine("Label Held");
e.Handled = false;
}
}
}
Running this we find that
Bubbling actually occurs by default in windows. If we wanted we could turn off bubbling by changing
e.Handled = true;
In our Label Renderer and the frame would never get notified of the Hold Event.
Now For Android
On Android things get a bit messier. Again we'll create two renderers.
[assembly: ExportRenderer(typeof(Label), typeof(myLabelCustomRenderer))]
[assembly: ExportRenderer(typeof(Frame), typeof(myFrameCustomRenderer))]
namespace App4.Droid
{
public class myFrameCustomRenderer : FrameRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Frame> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
this.Touch += myFrameCustomRenderer_Touch;
}
}
void myFrameCustomRenderer_Touch(object sender, Android.Views.View.TouchEventArgs e)
{
System.Diagnostics.Debug.WriteLine("You Touched My Frame");
e.Handled = false;
}
}
public class myLabelCustomRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Label> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
this.Touch += myFrameCustomRenderer_Touch;
}
}
void myFrameCustomRenderer_Touch(object sender, Android.Views.View.TouchEventArgs e)
{
System.Diagnostics.Debug.WriteLine("You Touched My Label");
e.Handled = false;
}
}
}
If we run this it appears that everything works the same as windows we geta touch event in the label and a touch event in the Frame. The bubbling up appears to be automatic. It Gets messy when we attempt to disable bubbling. If we change
e.Handled=true;
in the Label Renderer and run the app again---
Touch fires twice IN THE LABEL RENDERER. Once for when we touch the screen and once for when we stop. If we set the labelrenderer's e.Handled=false; and set the Frame to true. Then the label touch fires followed by the Frame but only the Frame Fires the second time.
In addition if we remove e.Handled=false from both renderer and run the app we find that only the LabelRenderer's Touch event fires. Implying that the default for Handled appears to be true. If you do not set e.Handled=false in the renderer the event will fire in the LabelRenderer and not bubble up the stack to the FrameRenderer.
In Conclusion:
Bubbling works out of the box on Windows. On Android it doesn't work like you might expect. First you have to explicitly set the Handled=false in every child so the parent gets notification and even then only the Handler that Handled the event gets notified that the touch event ended the rest of the stack gets notified of the start but never knows its over.

Windows form click event for panel does not work when another object is using it as a handle

I have an IC Image Control Grabber that is using a panel in a windows form as a handle (embedding the camera input in the form). I want to be able to click at some point on the panel and get the coordinates of the click in that panel. I have written that function and it works great before I embed the camera input. However, as soon as the camera is embedded the click event is not triggered when I click in the panel. Any ideas on what I can do to fix this problem?
Here is the documentation for the Grabber Object: (I call the setHWND() function)
http://www.imagingcontrol.com/en_US/support/documentation/class/Grabber.htm
Here is the relevant code I have written:
System::Void liveFeedPanel_Click(System::Object^ sender, System::EventArgs^ e)
{
System::Drawing::Point cursorPoint = liveFeedPanel->PointToClient(Cursor->Position);
//do something with that point
}
System::Void MainForm_Load(System::Object^ sender, System::EventArgs^ e)
{
HWND hwnd = static_cast<HWND>(this->liveFeePanel->Handle.ToPointer());
imageController->startCamera();
imageController->startLive(hwnd);
}
void ImageController::startLive(HWND hwnd)
{
if (grabber.isDevValid()) {
grabber.setHWND(hwnd);
grabber.setDefaultWindowPosition(false);
grabber.setWindowSize(//the new size);
grabber.startLive(true);
}
}
Thanks!
The solution I found was to use the MouseDown event instead of the Click event. This ignored what was being clicked on in the panel and simply looked at wether the mouse was within the panel.

How to stop reload page after navigation windows phone?

My mainpage call to Page1. I add a webbrowser control to the Page1. When the webbrowser load data complate, I go the background.Then, i back my Page1, webbrowser reload data. How to stop reload it?
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
_mlink = NavigationContext.QueryString["link"];
web.Navigate(new Uri(_mlink, UriKind.Absolute));
}
You can use the NavigationEventArgs.NavigationMode property to determine which direction the navigation is coming from.
The available options can be found here (MSDN), but listed out, they are:
New
Back
Forward
Refresh
So my tip would be to determine which value of this you want to navigate the web browser control on (I would guess New).
NavigationEventArgs.NavigationMode works only in windows phone 8. So edit the code like this.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
_mlink = NavigationContext.QueryString["link"];
if(web.Source.AbsolutePath!=_mlink)
web.Navigate(new Uri(_mlink, UriKind.Absolute));
}

Is it possible to preload an assembly in Windows Phone 7?

I have an app in which I have a lot of references and the load time was not acceptable to me. I have removed the splash screen image and created an animated loading screen by having a separate project with no reference to the main application which then navigates to the first page of the rest of the app. It does start up fast now but it's a little lacking still.
I would like to do another animation right before the load screen goes away. The only way I can think of to do this is to actually preload the assemblies needed for the navigation to the next page, do an animation, and then navigate.
I have tried
OnNavigatedFrom but the animation doesn't have time to run since the page will be replaced by the new page very quickly from that point.
OnNavigatingFrom is no help either as it is called as soon as I call NavigationService.Navigate();
Searching the web and Stack Overflow :)
I also considered faking it a bit by having the next page show a duplicate of the load screen and do the last animation there, but it can't match the current state of the load screen animation and is harder to maintain
Thanks for any ideas!
If you want to force the loading of an assembly, just reference a type from this assembly.
For instance, something like Console.WriteLine(typeof(YourAssembly.SomeType)); will force the loading of YourAssembly.
Now for your problem, maybe you can use usercontrols? Put the content of your main page in a user control. Display the loading page, create the usercontrol in the background, let the animation play, then when the animation is done playing replace the page's content with the usercontrol.
It turns out that you can preload by just creating a new instance of the page you are going to navigate to. Unfortunately that has to be done on the UI thread which can cause animation slowdown, at least in my experience.
Here is a sample of how to do an animation, then preload, then do another animation before navigating. :
public partial class LoadScreen : PhoneApplicationPage
{
public LoadScreen()
{
InitializeComponent();
this.Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
var sb = new Storyboard();
// create your animation here
sb.Completed += (sender, args) => PreLoad();
sb.Begin();
}
private void PreLoad()
{
// this is the part that actually takes time and causes things to get loaded
// you may need it in a try/catch block depending on what is in your constructor
var page = new PageToNavigateTo();
// now create an animation at the end of which we navigate away
var sbOut = new Storyboard();
// create your animation here
sbOut.Completed += (sender, args) => NavigateToNextScreen();
sbOut.Begin();
}
private void NavigateToNextScreen()
{
// navigate here
}
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
// remove the loading screen from the backstack so the user doesn't see it again when hitting the back button
NavigationService.RemoveBackEntry();
}
}

WebBrowser control: show to user when it's navigating

I'm developing a Windows Phone application.
I'm using WebBrowser control and I want to show to users when is loading a page. I've used events:
private void Browser_Navigating(object sender, Microsoft.Phone.Controls.NavigatingEventArgs e)
{
LoadingText.Visibility = System.Windows.Visibility.Visible;
}
private void Browser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
LoadingText.Visibility = System.Windows.Visibility.Collapsed;
}
But it doesn't work.
Any advice?
I think your problem is in the navigated event - this
From msdn
Occurs when the WebBrowser control has navigated to a new document and has begun loading it.
This obviously could be long before the document is actually rendered.
I'm not sure there's any event to use to determine when the page is fully loaded and is rendered.
In iron7, I detect when the editor is loaded by using a timer - that timer keeps trying to call javascript methods in the script - I know these are only available after the document javascript ready occurs.
Try using the LoadCompleted event:
private void Browser_LoadCompleted(object sender, NavigationEventArgs e)
{
LoadingText.Visibility = System.Windows.Visibility.Collapsed;
}
This ensures that once everything is rendered the loading bar will disappear.
See the msdn page: http://msdn.microsoft.com/en-us/library/microsoft.phone.controls.webbrowser.loadcompleted(v=VS.92).aspx
(I think Stuart was looking at the Windows Forms implementation of WebBrowser rather than the Phone Control)

Resources