Metro App SuspensionManager Override SaveState Behaviour - windows-runtime

How do I modify the SuspensionManager object in a Metro App, to SaveState for the MainPage only and discard State and Navigation for any child pages?
E.g. I have a MainPage that allows you to Navigate to a ChildPage. If the Metro App is Closed or Suspended, I want the ChildPage to override the MainPage state values.
Now, the next time the user opens the app, the MainPage should open and not the ChildPage. Also the MainPage should show State that the ChildPage updated before the app was Closed or Suspended.
Any ideas on how the SuspensionManager object can be safely modified to accomplish this?

Why not just add your data from the ChildPage to the SessionState dictionatry and fill it into the MainPage when the app resumes ?
You don't even need to modify the SuspensionManager for doing that!
public BasicPage1() {
this.InitializeComponent();
Application.Current.Suspending += Current_Suspending;
Application.Current.Resuming += Current_Resuming;
}
void Current_Resuming( object sender, object e ) {
var name = SuspensionManager.SessionState["name"].ToString();
}
void Current_Suspending( object sender, Windows.ApplicationModel.SuspendingEventArgs e ) {
SuspensionManager.SessionState.Add( "name", "danielovich" );
}

Using the suggestion from Danielovich (which is NOT complete), the solution is 2 parts:
Firstly:
No longer save state in the pageState object, instead save state
using the SessionState object. Why? This is so that all Pages can share the same State information.
Secondly:
To ensure, that NavigationState is not saved so that MainPage is always the default page, we need to change the SaveFrameNavigationState in SuspensionManager as follows:
private static void SaveFrameNavigationState(Frame frame)
{
var frameState = SessionStateForFrame(frame);
frame.GetNavigationState();
frameState["Navigation"] = "1,1,0,15,Skycap.MainPage,12,0";
}

Related

Windows Phone, Prism.StoreApps: How to avoid activation of a certain page after suspension or termination?

I do want to ensure that in case an app is navigated to a certain page, the app is on another (in my case the previous) page after it was suspended or terminated. In my case the page is for taking photos. I do not want the user to return to this page after the app was in the background since it has no context information. The context information is on the previuos page.
How could I achieve this with Prism.StoreApps?
Background: If an app was just suspended the state of the app remains after it was resumed, hence the last active page is active again. I have no real idea how to set another page active in this case. If an app was terminated Prim.StoreApps restores the navigation state and navigates to the last active view model (hence to the last active page). I do not know either how to alter the navigation state in this case so that another page is navigated to.
In the meantime I fond a working solution myself. Might not be the best and there might be better solutions, but it works.
For resuming the app I handle the Resuming event:
private void OnResuming(object sender, object o)
{
// Check if the current root frame contains the page we do not want to
// be activated after a resume
var rootFrame = Window.Current.Content as Frame;
if (rootFrame != null && rootFrame.CurrentSourcePageType == typeof (NotToBeResumedOnPage))
{
// In case the page we don't want to be activated after a resume would be activated:
// Go back to the previous page (or optionally to another page)
this.NavigationService.GoBack();
}
}
For the page restore after termination I firstly use a property in the App class:
public bool MustPreventNavigationToPageNotToBeResumedOn { get; set; }
public App()
{
this.InitializeComponent();
// We assume that the app was restored from termination and therefore we must prevent navigation
// to the page that should not be navigated to after suspension and termination.
// In OnLaunchApplicationAsync MustPreventNavigationToPageNotToBeResumedOn is set to false since
// OnLaunchApplicationAsync is not invoked when the app was restored from termination.
this.MustPreventNavigationToPageNotToBeResumedOn = true;
this.Resuming += this.OnResuming;
}
protected override Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args)
{
// If the application is launched normally we do not prevent navigation to the
// page that should not be navigated to.
this.MustPreventNavigationToPageNotToBeResumedOn = false;
this.NavigationService.Navigate("Main", null);
return Task.FromResult<object>(null);
}
In OnNavigatedTo of the page I do not want to be activated on a resume I check this property and simply navigate back if it is true (and set the property to false to allow subsequent navigation):
public override void OnNavigatedTo(object navigationParameter, NavigationMode navigationMode,
Dictionary<string, object> viewModelState)
{
if (((App)Application.Current).MustPreventNavigationToPageNotToBeResumedOn)
{
// If must prevent navigation to this page (that should not be navigated to after
// suspension and termination) we reset the marker and just go back.
((App)Application.Current).MustPreventNavigationToPageNotToBeResumedOn = false;
this.navigationService.GoBack();
}
else
{
base.OnNavigatedTo(navigationParameter, navigationMode, viewModelState);
}
}

Want to create an automation that switches between two tabs

I am new to automation and want to create an automation test which can do following:
Open one tab --- click and get some info from that tab
Switch to another tab --- click and get some info from this tab now.
Compare the infos.
We use Page Object Model to get info from one page. However the moment, I switch to another tab -- it switches the tab successfully but does not locate any element on it.
Any idea ?
Questions I would ask is,
Is the element locator correct?
Is this a unique element locator?
Is this a synchronization issue? Are you waiting enough for the page to load before finding the element?
Is this problem particular to a browser? Is it consistent across?
Also make sure you pass on the driver object from one page object to the other. Like,
public class PageOne {
public PageOne(WebDriver driver) {
//do something in constructor
}
public void someMethodInPage1() {
driver.findElement(By.id("button1")).click();
PageTwo pageTwo = new PageTwo(driver);
pageTwo.someMethodInPage2();
}
}
public class PageTwo {
private WebDriver driver;
public PageTwo(WebDriver driver) {
//do something in constructor
this.driver = driver;
}
public void someMethodInPage2() {
driver.findElement(By.id("button2")).click();
}
}

Create custom presenter for my mvvmcross project

I'm working on a project for iOS using mvvmcross.
App navigation goes like this: first it starts from the splash screen (1), them it navigates to (2), a view to select between 3 options, in view (3) and (4) you get a list and also could navigate back to (2), if you select an item in (3) you navigate to (5) in a modal way.
Lastly, all navigation end up in (6), a view with an hamburger menu.
So I have traditional navigation(with back button), modal views and a hamburger menu at the end.
It would be great if someone could help me or guide me to see how to create a custom presenter for this navigation scheme.
I'm using MvxModalNavSupportTouchViewPresenter and a SlidingPanelsNavigationViewController, but don't know how to swap them when I navigate from (2,4,5) to (6)
A presenter is just something that implements https://github.com/MvvmCross/MvvmCross/blob/develop/MvvmCross/Core/Core/Views/IMvxViewPresenter.cs
public interface IMvxViewPresenter
{
void Show(MvxViewModelRequest request);
void ChangePresentation(MvxPresentationHint hint);
}
This is are really simple interface and it allows shared portable code like ViewModels to request changes in the display.
For the case where you want a Show request to change the entire UI from one display paradigm (modal navigation controller) to another (sliding panels), then one way to do this is to implement a presenter which has two child presenters and which simply switches them over.
In pseudo code this might look like:
public class MyPresenter : IMvxViewPresenter
{
private IMvxViewPresenter _currentPresenter;
private ModalPresenter _modalPresenter;
private SlidingPresenter _slidingPresenter;
private enum Style
{
Modal, Panels
}
private Style _currentStyle;
public MyPresenter()
{
// do whatever you need to do here to:
// - construct _modalPresenter and _slidingPresenter
// - make _modalPresenter attached to the window (via root view controller)
// - make _slidingPresenter hidden/unattached
_currentStyle = Style.Modal;
_currentPresenter = _modalPresenter;
}
public void Show(MvxViewModelRequest request)
{
if (_currentStyle == Style.Modal &&
request.ViewModelType == typeof(WhateverViewModelIndicatesTheSwitchIsNeeded))
{
DoSwitch(request);
return;
}
_currentPresenter.Show(request);
}
public void ChangePresentation(MvxPresentationHint hint)
{
_currentPresenter.ChangePresentation(hint);
}
private void DoSwitch(MvxViewModelRequest request)
{
// do whatever is necessary to:
// - remove _modalPresenter from the window
// - add _panelPresenter to the window
// - show `request` within _panelPresenter
_currentPresenter = _panelPresenter;
_currentStyle = Style.Panelsl
}
}
Obviously, there are some details to fill in within this pseudo-code - e.g. there are some viewcontrollers to be added and removed from the window - but this is just standard iOS manipulation - e.g. see lots of questions and answers like Changing root view controller of a iOS Window and Change rootViewController from uiviewcontroller to uinavigationcontroller

how to display a video from a JList?

I am currently doing an application using Swing and i am stuck at a certain point. In my function, i have to link videos from a JList. The problem is i am not sure how to link the videos from the JList. I am using an OpenBrowser class to link the video to the internet. I did consider using JButton but i would have to hardcode it and that would be ugly. Is there any other alternatives to do this? I am in desperate need and would be eternally grateful to whoever that can help me.
Safa :)
If you don't want to open a browser with the video using a selection listener, you can consider the idea of launching it with a double click on a JList entry.
sample code
String[] items = {"i1", "i2", "i3", "i4"};
JList list = new JList(items);
list.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt) {
JList list = (JList)evt.getSource();
if (evt.getClickCount() == 2) { //check if it is a Double-click
int index = list.locationToIndex(evt.getPoint());
// do whatever you want with the entry at that index
}
}
});
Desktp classes to browse some site (sample code):
if (desktop.isSupported(Desktop.Action.BROWSE)) {
URI uri = new URI("http://www.google.com");
desktop.browse(uri);
}
The desktop.browse() call will open your favourite browser with the given URL.

removing mouse events/controls from swing components with glasspane

I have a client-server application and i am using swing in the client side. My swing client has one main window (jframe) and lots of panels, toolbars and menubar in it.
I want to remove all client action/mouse events (or simply grab and do nothing) while client is waiting response from server by means of glasssPane.
Here is the code i wrote:
private final static MouseAdapter mouseAdapter = new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
System.out.println("MouseClicked..!");
}
};
private static Cursor WAIT_CURSOR = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
private static Cursor DEFAULT_CURSOR = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
and
public static void startWaitCursor(JComponent comp)
{
MainWindow root = ((MainWindow) comp.getTopLevelAncestor());
root.getGlassPane().setCursor(WAIT_CURSOR);
root.getGlassPane().addMouseListener(mouseAdapter);
root.getGlassPane().setVisible(true);
}
public static void stopWaitCursor(JComponent comp)
{
MainWindow root = ((MainWindow) comp.getTopLevelAncestor());
root.getGlassPane().setCursor(DEFAULT_CURSOR);
root.getGlassPane().setVisible(false);
}
but i am not able to manage the grab mouse events. Changing cursors at the glassPane is working fine but either i am not able to add mouseAdapter or am not able to make glasssPane become to the top level component.
Any idea?
Thanks.
I realized that my code is working but my problem is threading related. My code was something like:
startWaitCursor();
work(); // server request that takes time
stopWaitCursor();
and changed it to:
startWaitCursor();
SwingUtilities.invokeLater(new Runnable() {
poblic void run() {
try
{
work(); // server request
}
finally
{
stopWaitCursor();
}
by doing this modification i could see the settings i made in the startWaitCursor() method while client is waiting response from the server.
But stil there is a small problem. In startWaitCursor() method i desabled key, mouse and focus events for the glass pane but events are still captured by main frame even glassPane is displayed.
addMouseListener(new MouseAdapter() {});
addMouseMotionListener(new MouseMotionAdapter() {});
addKeyListener(this);
setFocusTraversalKeysEnabled(false);
After server response reached to client and stopWaitCursor() method is invoked the events handled in the main frame.
If i disable the main frame of my application while client is waiting than cursor is not being changed to wait_cursor, if i am not disable the main frame then cursor is being changed but the events are queued.
cheers...
After digging swing threads issues couple of days, i finally found the real answer: SwingWorker
Now my final code is something like,
startWaitCursor();
SwingWorker worker = new SwingWorker() {
public Object doInBackground()
{
doWork(); // time consuming server request
return null;
}
public void done()
{
stopWaitCursor();
}
};
worker.execute();
In startWaitCursor() method i set the glasspane visible (with alpha valued background), display a message to warn the user time consuming job is doing, set the cursor to wait_cursor (hourglass) and consume all the key, mouse events. That is it.
And by using SwingWorker my client is actually responsive (it is working as if no server request is made) but since i display the glasspane and consume all key and mouse events it feels like irresponsive.
What a relief.. SwingWorker rocks...
cheers..