Close view model (navigate back) in Init - mvvmcross

I'm attempting to call Close(this) in Init in a ViewModel to navigate back, but I'm receiving the following from Mvvmcross in the debug output when running on Android.
mvx:Warning: 7.59 Ignoring close for viewmodel - rootframe's current page is not the view for the requested viewmodel
Is it possible to Close here?
Maybe I'm approaching this wrong. I want to open a connection based on a string I'm passing in Init and if it fails, show a toast (or equivalent notification) and go back.

No. Nor can you do it in Start.

Related

MvvmCross: Calling Close on my viewmodel crashes Store app

I have an application that crashes when I call Close(this) in the viewmodel at level 2 (meaning can go back one page). One at level 3 (meaning can go back two pages) goes back fine.
I call this in the main app:
// Register the main view model
Mvx.RegisterSingleton<IMvxAppStart>(new MvxAppStart<StartScreenViewModel>());
In StartScreenViewModel I call
this.ShowViewModel<AddNewViewModel>();
And that viewmodel has a ICommand binding in the XAML that calls a function that calls:
this.Close(this);
When calling this Close(), I end up in the UnhandledException handler.
The exception message is:
The given key was not present in the dictionary.
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at Cirrious.MvvmCross.WindowsCommon.Views.MvxWindowsPage.LoadStateBundle(NavigationEventArgs e)
at Cirrious.MvvmCross.WindowsCommon.Views.MvxWindowsPage.<>c__DisplayClass1.<OnNavigatedTo>b__0()
at Cirrious.MvvmCross.WindowsCommon.Views.MvxWindowsExtensionMethods.<>c__DisplayClass1.<OnViewCreate>b__0()
at Cirrious.MvvmCross.WindowsCommon.Views.MvxWindowsExtensionMethods.OnViewCreate(IMvxWindowsView storeView, Func`1 viewModelLoader)
at Cirrious.MvvmCross.WindowsCommon.Views.MvxWindowsExtensionMethods.OnViewCreate(IMvxWindowsView storeView, MvxViewModelRequest viewModelRequest, Func`1 bundleLoader)
at Cirrious.MvvmCross.WindowsCommon.Views.MvxWindowsPage.OnNavigatedTo(NavigationEventArgs e)
What could cause this?
After some more digging and wondering about navigation, I figured it out.
I had overridden
OnNavigateFrom(...)
in the StartScreenViewModel, but had not called
base.OnNavigateFrom(...)
in the function body! Adding that called now allows navigation to work correctly. Noob!
I believe that by default Windows Store apps dispose of pages that are not on the top of the navigation stack. You can override this behaviour.

ServiceLocationProvider is null when launched as a Share Target

I'm using MVVM Light and everything is fine except when launching my Windows Phone 8.1 WinRT app as a Share Target.
When I try to assign MainViewModel viewModel = ServiceLocator.Current.GetInstance<MainViewModel>(); I get an exception for ServiceLocator.Current.
Exception Message: ServiceLocationProvider must be set.
Do I need to do something extra in App.xaml.cs OnShareTargetActivated event to insure the Locator is running?
UPDATE:
A ShareTarget page needs to be thought of as a small extension of your app. It seems that not all of the app's resources are loaded (including app-wide resources in App.xaml). So I just created a new instance of MainViewModel in the share page's constructor, loaded only the things I need for the share to complete, save the information and call ShareOperation.ReportCompleted. This returns the user back to the app that is sharing.
I still haven't found a good solution for getting other resources in my ViewModel, but this works for now.
This indicates that the following line has not been executed:
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
This line will instruct the ServiceLocator class to use the SimpleIoc.Default instance as its ServiceLocator.Current. When you run your app as a Share target, the initialization is slightly different and probably the ViewModelLocator doesn't get initialized. You need to find a good location to perform the initialization before you use the ServiceLocator.
Cheers
Laurent

Prism with WinRT how can I force a fresh start when resuming from termination?

I am building a WinRT App, that uses proximity, and WiFi direct for peer to peer communication. As a result, when the app terminates, and then resumes I need it to start fresh (the connections will be closed, and can't be reopened without user interaction). The problem is that the Prism MvvmAppBase class that I am inheriting my app from is doing something that is causing it to try to resume from a saved state (that does not exist) and the app ends up on the last screen shown, but there is no ViewModel backing it, and so depending on the view, it will just sit unresponsive, or crash.
I am looking at this guide for guidance, and it says that unless there is a way to start fresh, but I cannot seem to find how to actually do that. http://msdn.microsoft.com/en-us/library/windows/apps/xx130647.aspx
I have been hacking around in the App.cs file to try and get it to work. There is really nothing at all in the App.cs file now except for the unity container and prism bootstrapping, and a call to NavigationService.Suspending() in the Suspending event handler.
The bootstrapping looks like this, but it is never called when the app is resumed from Termination.
protected override async void OnLaunchApplication(LaunchActivatedEventArgs args)
{
await BootStrapper.Config(_container);
await BootStrapper.RegisterPrismInstances(_container, NavigationService, SessionStateService, FlyoutService);
NavigationService.Navigate("Main", null);
}
If anyone has dealt with this before, and can point me in the right direction, I would really appreciate it.
When a Prism WinRT app is re-launched after being Terminated Prism will try to restore the application state, the Frame's navigation stack and the Frame's state before being terminated (which will navigate to the last opened page and try to restore any properties in the view model that are marked with the RestorableState attribute.)
By looking at the MvvmAppBase's source code it seems that there are a couple of things you could try to prevent Prism for saving / restoring the application state:
Create a default constructor in your App class that would clear the handlers of the Suspending event. The default constructor of the MvvmAppBase registers to this event and saves the state when it's raised.
Override the OnLaunched method of the base class. In it, after executing the base method, check if the previous executing state is Terminated. If so, you could clear the navigation history of the NavigationService and navigate to your start up page. The saving and restoring operations will still execute though, so any registered service will still be restored to its previous state. (This cannot be done in the OnLaunchApplication as it's not invoked if the application's state was successfully restored.)
Also, you could also try to completely remove this functionality from the MvvmAppBase class. However, most of its methods related to saving / restoring the application state are private, so you might as well drop the MvvAppBase, copy its entire code in your App class and edit it accordingly.
I have not tried any of the approaches listed above so I'm unaware if they could generate any problem, but they might help you as a starting point.

System.TypeInitializationException between two program in F#

I'm working on a project and I become always an Exception "TypeInitializationException".
I tried to give a string to a global string variable but it failed.
That's the code for the viewmodel and it failed on the second line
| {State = _}, ConsumablesClicked vm ->
Testtyp <- vm.TrackPosition.ToString()
That's on the other program
let mutable Testtyp = ""
I become this InnerException "Cannot read keys when either application does not have a console or when console input has been redirected from a file. Try Console.Read.".
"The type initializer for '.$BarcodeGenerieren' threw an exception.", that's the exception explication.
Has someone a Idea how solve this?
That exception indicates that some code is trying to call Console.ReadKey when the standard input for that process has been redirected (see e.g. Allowing redirection of StandardInput of a C# application when doing "Console.ReadKey"). The solution is not to call Console.ReadKey, but it's not clear from your description where this is actually happening (perhaps in the static constructor for one of your types?).
I found the solution after a lot of try and it was only, that I had a Console.Readkey in my code, that I forgot to delete.
I had before a console apllication and I transformed it to be a class.

How to get WcfFacility and Wcf global exception handling working?

I have deployed my service and attached Visual Studio to the process to debug in one Visual Studio instance, and in another I have a client console test application that I run in debug mode, I can see both service methods that I call executed in the debugger, but in the second one where I throw an exception on purpose, I never see the code in ErrorHandlerBehavior called at all.
Is my registration for ErrorHandlerBehavior not correct?
I wonder if I need to have a behaviour extension in my service configuration for this?
I based my global exception handling off of the this example
Here is my container registration in my service program main method:
container.AddFacility<WcfFacility>(f => f.CloseTimeout = TimeSpan.Zero);
container
.Register(Component.For<WcfProtoType.IServiceProtoType>()
.ImplementedBy<WcfProtoType.ProtoTypeService>()
.Named("ProtoTypeService")
.AsWcfService( new DefaultServiceModel()
.AddEndpoints(WcfEndpoint
.BoundTo(new BasicHttpBinding(BasicHttpSecurityMode.None))
.At(baseUrl)
).PublishMetadata(o => o.EnableHttpGet())),Component.For<ServiceBase>().ImplementedBy<MyService>(),
Component.For<ErrorHandlerBehavior>().Attribute("scope").Eq(WcfExtensionScope.Services));
I looked at the Castle Windsor source and from what I can tell the EndPointBehavior needs to be registered first like this:
container
.Register(Component.For<ErrorHandlerBehavior>().Attribute("scope").Eq(WcfExtensionScope.Services),
Component.For<WcfProtoType.IServiceProtoType>()
.ImplementedBy<WcfProtoType.ProtoTypeService>()
.Named("ProtoTypeService")
.AsWcfService( new DefaultServiceModel()
.AddEndpoints(WcfEndpoint
.BoundTo(new BasicHttpBinding(BasicHttpSecurityMode.None))
.At(baseUrl)
).PublishMetadata(o => o.EnableHttpGet())),Component.For<ServiceBase>().ImplementedBy<MyService>());