Caliburn.Micro and app resume - c#

In my Windows Phone Silverlight 8.1 app I enabled the app resume (ActivationPolicy="Resume")
When the user re-open the app (using the main tile), the OnDeactivate method of the ViewModel is called after the OnActivation method.
Is it correct?
How can I handle the app resume with Caliburn.Micro?
Here is the code of the ViewModel:
public class Page2ViewModel: Screen
{
protected override void OnActivate()
{
base.OnActivate();
}
protected override void OnDeactivate(bool close)
{
base.OnDeactivate(close);
}
}

This does not seem right. OnDeactivate is called when navigating away from a View. In your ViewModel there is no way to directly differentiate if it was activated from normal navigation or because of resuming.
Take a look at your Bootstrapper, you can override OnActivate and OnLaunch methods there that correspond to Application_Launching and Application_Activated. OnActivate is the one you want.

The problem was in the AppBootstrapper.
To handle the app fast resume, the Navigated and Navigating events must be subscribed in the CreatePhoneApplicationFrame frame.
In this repository the fix (see commit list for the history).

Related

Xamarin.Forms physical key press event handling

I'm developing Xamarin Forms app and I need to handle an event when physical button is pressed (on Android). What I've found out is that I can use DispatchKeyEvent inside an activity in Xamarin.Android project. However I don't know specifically how to do it.
In the shared code I have defined a ContentPage and I'm trying to override the DispatchKeyEvent inside a custom page renderer in Xamarin.Android. However, I get an error about missing constructor (I suppose it is related to layout, which is defined in the shared code, but I don't know why Xamarin.Android renderer doesn't use it).
How to solve this problem? Maybe there is some easier way to get info about key being pressed?
In the code behind for your page, you can override OnBackButtonPressed.
protected override bool OnBackButtonPressed()
{
return base.OnBackButtonPressed();
}

OnBackPressed Xamarin PCL where do i override the method

I am trying to override the OnBackPressed() method in a pcl project. I do not know where i must ovveride it. In the portable project or in the android? I want to navigate to another page when i click the back button. Any suggestions?
You need to override OnBackButtonPressed in your PCL project on your custom Page classes.
protected override bool OnBackButtonPressed()
{
// call your custom navigation code here
// returning true because you are handling the navigation
return true;
}
Note that this event is raised when the hardware back button is pressed but will not be raised on iOS.

How to intercept Navigation Bar Back Button Clicked Prism Xamarin Forms?

Basically Its the same question from Here but the solution dosen't work for Prism MVVM because the OnOptionsItemSelected(IMenuItem item) in the MainActivity never get raised.
For the hardware button I'm using on that page:
protected override bool OnBackButtonPressed()
{
return !PageUtilities.CanNavigate(this, null);
}
Found the answer here https://xamarindevelopervietnam.wordpress.com/2016/11/19/how-to-handle-hardwaresoftware-back-button-from-viewmodel-in-xamarin-forms/
works well
you can do like this
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
e.Cancel = !PageUtilities.CanNavigate(this, null);
base.OnBackKeyPress(e);
}
Cancel the event when navigation neeeds to be stopped
I guess there is no straight or single answer to this.
Based on your requirement you must need to provide MVVM implementation.
Latest Prism Library update has the OnNavigatedFrom method (you'll require to override by implementing INavigationAware interface)
public virtual void OnNavigatedFrom(NavigationParameters parameters)
{
// here is the place you would require to handle the Back button event,
// this is fired every-time, user tries to leave the view.
}
public virtual void OnNavigatedTo(NavigationParameters parameters)
{
// fired upon view load
}
You may require a static (boolean or something) variable to keep a check if the user is leaving the view and optionally display a message or invalidate the action.
Hope this helps.
Regards,
N Baua

Doing navigation in App.xaml.cs within resume handler

I have a C#/XAML Windows Store App and I need to be able to perform some network/RESTful API tests in the resume handler to make sure that a token/session is still valid. If it isn't, the app needs to direct the user back to the login page.
I've tried a number of solutions on SO and for one reason or another, they won't work from within App.xaml.cs. The overarching issue seems to be my inability to get to Frame.Navigate from within the resume handler.
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
Application.Current.Resuming += new EventHandler<object>(OnResuming);
}
private async void OnResuming(object sender, object e)
{
bool success = true;
// some tests are performed here
if (!success) { /* what do I use here? */ }
}
I've tried solutions on the following pages:
Run code on UI thread in WinRT
http://social.msdn.microsoft.com/Forums/windowsapps/en-US/6228490a-0fd8-46ce-adc6-b8d161eeec68/update-ui-when-using-threadpool?forum=winappswithcsharp
Request UI navigation using PRISM 4 on an asynchronous WCF response thread
WPF/C# Don't block the UI
In your example your handling the Resuming event from within your Application class as opposed to somewhere else. You can attach a resuming handler anywhere even within your application pages.
This example from MSDN (How to resume an app) binds the resume handler directly on the MainPage class where you should have no problem accessing the Frame.Navigate method. You could even create a PageBase class which adds this resume handler automatically so all of your pages can take advantage of this functionality.
Another solution is to just grab the root frame. The default WinRT sample app uses the following:
Frame rootFrame = Window.Current.Content as Frame;
So you should be pretty safe doing the same thing. Though you said that you were unable to get to Frame.Navigate for some reason so I'm not user if this is something you've already tried.
The main thing is to make sure that you're not blocking the UI thread at all. The Resuming event is not called on the UI thread so it won't block it by default but make sure you take advantage of async/await anyway, and use the Dispatcher to update any of the UI.

Caliburn.Micro screen transition via conductor

I have a Caliburn.Micro shell (i.e., an empty XAML view to contain other views) rendered by a Conductor ViewModel. From there I open a Screen via:
ActivateItem(...)
Usually from the newly displayed dialog the user can perform some operations and click buttons (OK, Cancel, Build....) which should each transition to another screen (in the shell).
public MyDialog : Screen
{
public void Ok()
{
// TODO: Somehow tell the conductor or called of this class about this action.
}
}
What are good ways to achieve these kind of dialog action/message screen transitions?
Simple .NET events are possible -- Wouldn't that be a bad idea?
CM IEventAggregator should also work by changing the view
Checking from the shell Conductor the ViewModel result once it has been closed via TryClose() -- Should be possible, just don't know how to achieve this in CM.
Reference the shell Conductor instance from that screen (via IoC or directly) -- That seems strong coupling.
Could you please advise.
My preferred approach is to use the EventAggregator to facilitate messaging between VMs.
This works especially well when you have multiple windows which are listening for a certain type of event (e.g. a Visual Studio style interface with multiple tool windows which may show context sensitive properties), however it sounds a little overkill for this implementation. Of course the advantages are still a good loose coupling between VMs and a lack of events (which is a good thing!)
It sounds like you want a modal dialog to popup and present an option, and then activate another screen once the first one has returned.
You can attach an event handler to the Deactivated event in the child VM which will fire when an item deactivates. It also passes a boolean in the arguments to notify if the item which deactivated was closed - you can check for this and activate the corresponding screen in your conductor.
e.g.
this.Deactivated += new EventHandler<DeactivationEventArgs>(WorkspaceViewModel_Deactivated);
void WorkspaceViewModel_Deactivated(object sender, DeactivationEventArgs e)
{
if(e.WasClosed) // raise some event
}
Then pass an event up to the conductor, I wouldn't really go the event route for this. This couples the VMs one-way so it may not be the most flexible solution
The alternative is to fire a message via the event aggregator to tell the conductor it needs to open a different window when the child VM closes. The same method can be used but it's decoupled
this.Deactivated += new EventHandler<DeactivationEventArgs>(WorkspaceViewModel_Deactivated);
void WorkspaceViewModel_Deactivated(object sender, DeactivationEventArgs e)
{
if(e.WasClosed) MainConductor.EventAggregator.Publish(new ActivateWindowMessage(typeof(SomeVM));
}

Categories