WP7 Application is being deactivated with no reason 10 seconds after navigating to a page - windows-phone-7

A WP 7.1 project starts with a Page that host a Panorama control. At some point user click on a ListBox, and this navigates the application to a details page.
In case the debugger is attached, everything stays on the screen as it should. But If I test an application either in emulator, or on the phone without a debugger, approximately in 5-10 seconds after the details page navigation, an application gets deactivated.
No unhanded exception, not closing, but deactivated even is raised. I have placed a message boxes in each of "exit handlers" to know exactly what happens and found out that it is deactivation.
No user input takes place after navigation and before the deactivation.
What may be the reason for such "no interaction" deactivation?
I don't call no "deactivate" requests from code.
Additional info:
Details page is bound to a sample view model that is obtained via MVVM Light ViewModel locator. View model locator gets it from ninject kernel that is a static public property of an App object(Yes, I have made IOC container publicly available via App property. I know it probably is a horrible practice, but I doubt the problem is linked to that). The page initializes just fine and displays all the data from a sample view model class. It almost seems like an app is deactivated due to inactivity, but there is no such thing in WP7 as far as I know.
UPDATE
A deactivation takes place exactly 10 seconds afer I call this line:
((PhoneApplicationFrame)(Application.Current.RootVisual)).Navigate(new Uri("/Views/BookDetailsView.xaml", UriKind.Relative));
from a view model of a main application view. The problem view is a details view, not the main one.
The constructor for BookDetailsView is empty (default):
public partial class BookDetailsView : UserControl
{
public BookDetailsView()
{
InitializeComponent();
}
}
The XAML for the view binds it's datacontext to a property of a mvvm light view model locator:
DataContext="{Binding Source={StaticResource Locator}, Path=BookDetails}"
The Locator resource is decleared in App.xaml and points to ViewModelLocator.cs.
The property that provides datacontext for a problem view is:
public static IBookDetailsViewModel BookDetailsStatic
{
get;
set;
}
/// <summary>
/// Gets the Main property.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
"CA1822:MarkMembersAsStatic",
Justification = "This non-static member is needed for data binding purposes.")]
public IBookDetailsViewModel BookDetails
{
get
{
return BookDetailsStatic;
}
}
The BookDetailsStatic is initialized from the IoC container call in the ViewModelLocator ctor:
BookDetailsStatic = App.Kernel.Get<IBookDetailsViewModel>();
In a any scenario the call to get an IBookDetailsViewModel returns an instance of a
public class SampleBookDetailsViewModel: IBookDetailsViewModel
which has an empty constructor and a bunch of properties.
SOLVED
My view, that I have been navigating to, was declared as a UserControl, and should have been as PhoneApplicationPage.

Hard to say without knowing what's on the page, but you could be hitting the memory limit.
In general, you can consider the memory limit to be 90mb, but you're better off checking DeviceStatus.ApplicationMemoryUsageLimit and DeviceStatus.ApplicationCurrentMemoryUsage and possibly displaying it on screen every half second or so to debug.
You can also try the profiler, assuming it doesn't affect the repro.

BookDetailsView was decleared as a UserControl.
Navigating to a UserControl deactivates an application in 10 seconds.
Changing the type of a view to PhoneApplicationPage solves the problem.

Related

Calling InitializeComponent in OnAppearing method in Xamarin Forms Project

Is there any reason or problem I cant call InitializeComponent method in OnAppearing function of a page in xamarin forms project?
I understand that I must call InitializeComponent only once to create the actual page. But what if I check that Content is already created and do it as below. Is it a bad implementation or practice? because it is said that no xaml based application does it and always call it in a constructor of the page.
reason I want to do it as below because xamarin.forms start up time is slow running on Android and if you use Masterdetail page(I think same for tabbed page), you must initialize it at the start up, it causes every navigation page defined in masterdetail page to be initialized and it costs you 2-3 secs depending on your UI could be even higher cost. any thoughts or experiences on this?
protected override void OnAppearing()
{
if (Content == null)
{
InitializeComponent();
}
}
I do not recommend this approach. From the xamarin docs.
The constructor of that class calls InitializeComponent, which then calls the LoadFromXaml method that extracts the XAML file (or its compiled binary) from the PCL. LoadFromXaml initializes all the objects defined in the XAML file, connects them all together in parent-child relationships, attaches event handlers defined in code to events set in the XAML file, and sets the resultant tree of objects as the content of the page.
https://developer.xamarin.com/guides/xamarin-forms/xaml/xaml-basics/getting_started_with_xaml/
If your forms are too slow on Android I would enable Fast Renders instead
In the OnCreate of your main activity add this line of code just before Xamarin.Forms.Init
Forms.SetFlags("FastRenderers_Experimental");
https://xamarinhelp.com/xamarin-forms-fastrenderers-android/
It would not hurt to try to use compiled Xaml also
using Xamarin.Forms.Xaml;
...
[XamlCompilation (XamlCompilationOptions.Compile)]
public class HomePage : ContentPage
{
https://developer.xamarin.com/guides/xamarin-forms/xaml/xamlc/

Some questions about Prism navigation in WPF

I thought that if you registered a view with the IoC container as "Singleton" then the same instance would be reused each time you navigate to it, while registering the view as "Transient" would create a new instance each time you navigate to it. Unless I'm doing something wrong, I've found that the IoC "lifestyle" makes no difference, and it's the IRegionMemberLifetime.KeepAlive property that dictates whether the view is re-used or recreated each time. Is this correct? (I'm using Castle Windsor IoC).
When Prism documentation talks about a view being "deactivated", is this simply the process of hiding the view when it is navigated from? And if KeepAlive=False, does the view get disposed at this point?
What about nested views/regions? If a view contains a region with another view inside of it, and I navigate away from the parent view, do both views get deactivated/destroyed (depending on the value of KeepAlive)? What about ClearChildViewsRegionBehavior - where does this fit into things?
I don't know if this apply to your situation but I implement the interface INavigationAware.
If a view should be reused for every navigation I always return true from the IsNavigationTarget method.
public bool IsNavigationTarget(NavigationContext navigationContext)
{
return true;
}

How to alter a DataTemplate based on a property on the page ViewModel in Windows Phone 7?

I have a ViewModel which contains a Boolean property which tells you if the user has authenticated or not.
I have a WrapPanel which is bound to a collection of profiles. The DataTemplate for these profiles has an icon - a closed padlock for when the user is not authenticated and an open one for when the user is authenticated. Ideally these would be bound to the Boolean on the ViewModel but the DataContext for the templates is the individual profile objects.
I have tried,
Setting the Source selector in the binding as specified here although it appear Windows Phone 7 does not support x:Reference
I tried also the Inversion of Control(?) method detailed here (but containerLocator was not found on my object)
I tried applying a Style.Trigger but these are not supported in Windows Phone 7
I also tried accessing the XAML elements in the code behind and updating programmatically on event triggers, however I could not get a handle on the Image element inside the DataTemplate
Edit after comment: WP7 does not support style triggers. But if anyone is looking for this answer on following versions I let the reply below:
I would use a Style Trigger as seen here to update the icon Source property on the fly - as part of the style of your DataTemplate so you would get a hold of your Image.
One way I found that works based on an answer by Damian Antonowicz but does not implement the full inversion of control method that he uses, is as follows,
Create a partial class which resolves to your view-model instance under your view-model namespace, e.g.
public partial class ViewModelInstanceLocator
{
public AppViewModel AppViewModel // Or whatever the type of your view-model is ...
{
get
{
return App.VM; // Or wherever your view model instance is ...
}
}
}
Define the other half of the class in your XAML page as a resource so that it can be referred to as a static resource, I did this in my App.xaml so that it could be referred to everywhere,
<ResourceDictionary>
<viewmodel:ViewModelInstanceLocator x:Key="ViewModelInstanceLocator" />
...
</ResourceDictionary>
You may need to include the relevant namespace if there is not already a reference to your view-model namespace e.g. at the top,
xmlns:viewmodel="clr-namespace:MyAppNamespace.ViewModel"
Finally to bind to the view-model as follows,
{Binding AppViewModel.SomeProperty, Source={StaticResource ViewModelInstanceLocator}}
The binding updates as usual just as if the view-model instance had been referred to through the DataContext. However, it does not work with design-time data.

How do you access the MainViewModel in ViewModelLocator from code behind?

Building a WP7 app using MVVM light for my view models. I'm using the ViewModelLocator that gets added when you add the library through NuGet. Works great but now I need to get access to a ViewModel from code.
In my code the user clicks a button and I need to search the MainViewModel (which contains several view models) and find one based on the criteria the user entered.
Normally I would just response to the Click event of the button but I don't have an instance variable of the ViewModelLocator class to get a hold of the MainViewModel to perform the search. With the default template (non-MVVMLight) for Windows Phone 7, the App class has a static variable to the main view model so you can access it anytime with App.ViewModel.
There's some talk from twitter about using commands which would be good, but at some point I have to perform a code search across multiple vms to get the results I need. Probably need to inject a ISearchViewModel service into the View or something to make this work.
Here's the implementation of ViewModelLocator that is provided:
public class ViewModelLocator
{
private static MainViewModel _main;
public ViewModelLocator()
{
_main = new MainViewModel();
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
"CA1822:MarkMembersAsStatic",
Justification = "This non-static member is needed for data binding purposes.")]
public MainViewModel Main
{
get
{
return _main;
}
}
}
So from the code behind of another view, how do you get access to Main (MainViewModel contains all the lists of data and has a search method I call)? Or Should you?
Just wondering how people are solving this type of problem?
Thanks.
In MVVM-Light the ViewModelLocator is provided as an application resource. Therefore you can still directly access it, but the syntax is different. If you look at your App.xaml you should see this piece of code somewhere.
<Application.Resources>
<vm:ViewModelLocator x:Key="Locator"
d:IsDataSource="True" />
</Application.Resources>
From anywhere in your application you can access the App's resources and therefore also the MainViewModel with this piece of code:
(App.Current.Resources["Locator"] as ViewModelLocator).Main
This works for any application resource.
If you created the ViewModelLocator as in the template you have static references to the ViewModels. The mvvmlocatorproperty-snippet creates ViewModel-properties like this.
This means that you could just instantiate a new ViewModelLocator to locate the ViewModels in your code behind button click. It will always be the same viewmodels independent of the different instances of the ViewModelLocator
To access the MainViewModel from your code you can add this property to your class:
public ViewModel.MainViewModel myContext { get { return (DataContext as ViewModel.MainViewModel); } }
Then you can just use myContext.[whatever]
You can just use ViewModelLocator.MainViewModelStatic. Default template for MVVMLight have a static property for each your viewmodel.

MVC using ASP.NET webforms

I've inherited an ASP.NET application built on top of webforms, and the application suffers from having all of its business logic embedded in the codebehind. As a result, this application can't be unit tested.
I want to break out the functionality of every form into an MVC style, but I've found that ASP.NET resists every effort on my part to refactor it. In general, I like to seperate my MVC classes as follows:
public class LoginModel
{
public string Username, Password;
public bool IsAuthenticated;
}
public interface ILoginView
{
event Action UserLoggedIn;
void SetMode(bool isAuthenticated);
}
public class LoginController
{
ILoginView View;
LoginModel Model;
public LoginController(ILoginView view, LoginModel model)
{
this.View = view;
this.Model = model;
// hook onto view events
}
}
Once I've got my classes set up and nicely unit tested, I can implement the ILoginView interface on my usercontrol or page:
public class LoginView : UserControl, ILoginView
{
public LoginView() : base()
{
new LoginController(this); // registers view with the controller
}
}
If this were a winform application, it would work beautifullly. But the ASP.NET lifecycle causes this style to break down.
ASP.NET creates and destroys the view on every page load. Since my Controller is held by the View, the Model is held by the Controller, every postback causes my page to lose its state.
I can remedy the problem above by holding my Controller in the users session, but that introduces a world of problems. In particular, putting Controllers in the session causes memory issues because Models and Controllersaren't reclaimed by garbage collection until the session expires. Navigating from page to page creates dozens of controllers, but the controllers don't dispose of themselves when the user navigates away from a page.
Since a view is destroyed/recreated on every postback, then I have to re-register the view with the controller on every postback. This is harder to do than it sounds, because the state of the Model needs to be copied back to the View on every postback, but simultaneously we don't want to overwrite a users changes to the View which were made in the previous postback. You have no idea what kind of additional nightmare this turns into when dealing with dynamically created or AJAXed controls using this MVC style.
I know I'm overthinking this and there is an easier way to get the results I want, but how do I implement an MVC style properly using webforms?
Is it not easier to re-write this using asp.net mvc?
As it seems you'll have to re-write. Either completely to MVC (and stop using DNN), or to a better WebForms implementation (meaning, separate logic from display and take into account the page life-cycle issues). There's a third option - combining MVC and ASP.NET WebForms, but you should look at it carefully taking into account all the variables in your platform.
Well the nature of the POSTback is dictating your state changes, so you should react on that. Any framework you use would work pretty much the same way, it'll rebuild/bind the state with each request. You should look into savind the state (read data) into your user's session.
ViewState should be used to store all the loaded data in WebForms, so the Controller would be instancied only when the page is created, eliminating the need to store any object in the user session.

Resources