How to fix crash problem when using WebView in SeparateProcess execution mode? - c#

In order to use WebGL in UWP WebView , I looked for this.
How do I enable WebGL in Xamarin.Forms WebView on UWP?
But a new problem comes. When navigating to another page and go back for a few times, the application crashed and gives you no explain. It seems like too many webview instance was created then I tried to use Singleton pattern to solve it.
public static class WebViewSingleton
{
private static WebView instance;
public static WebView GetInstance()
{
if (instance == null)
{
instance = new WebView(WebViewExecutionMode.SeparateProcess)
{
Source = new Uri("https://www.google.com/")
};
}
return instance;
}
}
public HomePage()
{
this.InitializeComponent();
MyWebView = WebViewSingleton.GetInstance();
MyWebView.Navigate(new Uri("https://sketchfab.com/models/a6af6d1ae2744a55820d00599aca71f2/embed?
autostart=1&internal=1&ui_infos=0&ui_snapshots=1&ui_stop=0&ui_watermark=0"));
this.RootGrid.Children.Add(MyWebView);
}
In this way, debugger tells me MyWebView is already a children for another element. I tried every way to disconnect MyWebView with it's parent but failed.
I find it works when adding NavigationCacheMode="Enabled" to my page, but that is not what I want.

add this to page.xmal
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
if (this.RootGrid.Children.Contains(MyWebView))
{
this.RootGrid.Children.Remove(MyWebView);
}
}

Related

How to deal with System.TypeLoadException in the app.xaml.cs in xamarin.forms?

Sorry to bother you, but I've come across a error in my code I don't how to deal with.
Whenever I try to run my app, I get faced with this:
System.TypeLoadException: 'Could not resolve type with token 01000019
from typeref (expected class
'Xamarin.Forms.Xaml.Diagnostics.VisualDiagnostics' in assembly
'Xamarin.Forms.Core, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=null')'
It states it occurs when the InitializeComponent(); is called in the constructor of App.xaml.cs.
Constructor in question:
public App()
{
//Line throwing the error
InitializeComponent();
MainPage = new NavigationPage(new Login.LogonFinal()); //Defines what page the app opens on when starting
}
App.xaml.cs
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace NEA_I_MDL
{
public partial class App : Application
{
static Databases.AccountDatabaseController AccountDatabaseVar;
public App()
{
//Line throwing the error
InitializeComponent();
MainPage = new NavigationPage(new Login.LogonFinal()); //Defines what page the app opens on when starting
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
public static Databases.AccountDatabaseController AccountDatabaseFunc
{
get
{
if(AccountDatabaseVar == null)
{
AccountDatabaseVar = new Databases.AccountDatabaseController();
}
return AccountDatabaseVar;
}
}
}
}
Thank you for reading, any tips/assistance will be a huge help for ineptly written code.
Can I ask that you please
Make sure you dont have different versions of the same Nugets in your solution.
Clean & Rebuild your Project
If That doesn't work for you try delete all your obj and bin folders and rebuild.
This usually happens because of Updates or version conflicts In my case atleast.
And do you mind showing us the LoginFinal Method?
I think you can just call Login
MainPage = new NavigationPage(new Login);

RegionManager.RequestNavigate only gets me System.Object?

I need to add some features to a WPF Project a retired colleague of mine made. Tried to copy the Navigation Features but they won´t work like they should.
I want to open my own XAML File in the Main Window but all I get is System.Object.
Here I register the Views as:
public override void Initialize()
{
UnityContainer.RegisterType<RelationView>();
UnityContainer.RegisterType<RelationNavigationItemView>();
UnityContainer.RegisterTypeForNavigation<RelationView>();
RegionManager.RegisterViewWithRegion(RegionNames.NavigationRegion, typeof(RelationNavigationItemView));//this works out fine appears in the Navigation Part
}
The RelationNavigationItemView is simply a button which should open the RelationView in the MainWindow.
Which should happen here as:
private static Uri RelationViewUri = new Uri("/RelationView", UriKind.Relative);
private IRegionManager _regionManager;
private DelegateCommand _navigateCommand;
public RelationNavigationViewModel(IRegionManager regionManager)
{
_regionManager = regionManager;
}
public ICommand NavigateCommand
{
get
{
return _navigateCommand ?? (_navigateCommand = new DelegateCommand(NavigateCommandExecute, NavigateCommandCanExecute));
}
}
private bool NavigateCommandCanExecute()
{
return true;
}
private void NavigateCommandExecute()
{
_regionManager.RequestNavigate(RegionNames.MainContentRegion, RelationViewUri); //Here should the new window appears and the ViewModel Constructor should be called but nothing happens, I only get System.Object in the MainContentRegion
}
The Project runs with Prism Version 6.3.
I hope, someone can help me.
Thanks and Best Regards, Max.
You should just navigate to ´"RelationView"`. No need for uri here, it just adds potential for errors.
Thanks Guys it works now. The Constructor was Wrong.
I expected an UnityContainer instead of a IUnityContainer.

Why does MvvmCross create a new ViewModel when back button is pressed

I'm building a Windows 8.1 mobile app with MVVMCross and I noticed some strange behavior when navigating between viewmodels.
I have 2 Viewmodels like so...
public class FirstViewModel : MvxViewModel
{
public override void Start()
{
base.Start();
}
public void Init()
{
//init code here
}
...
private void GoForward()
{
ShowViewModel<SecondViewModel>();
}
}
public class SecondViewModel : MvxViewModel
{
private void GoBack()
{
Close(this);
}
}
When I call Close(this) on SecondViewModel, Mvvmcross calls Start() and Init() on FirstViewModel again, like it was tombstoned.
Why does this happen? Even if I only leave FirstViewModel for a couple seconds, it seems to be tombstoned immediately. How do I stop this from happening? It's frustrating because I now have to maintain the state of FirstViewModel constantly.
You need to write the following line of code in your page constructor. This enables the caching of visited pages.
NavigationCacheMode = NavigationCacheMode.Required;

WinRT 8.1 settings in Caliburn.Micro

I'm trying to open a settings view in a Caliburn.Micro WinRT 8.1 app using VS2013 RC, but I keep getting an unhandled exception when opening it with the following message:
Value cannot be null. Parameter name: Could not parse the VisualElements from the app manifest.
I can reproduce the issues with the following steps:
create a new Windows Store app from VS2013 RC using the Blank app template.
add Caliburn.Micro via NuGet.
in App.xaml, change the base class to caliburn:CaliburnApplication (the namespace is declared as xmlns:caliburn="using:Caliburn.Micro").
in App.xaml.cs, change the class like this (for the CM-based settings I follow http://compiledexperience.com/blog/posts/settings-caliburn)
Code below:
public sealed partial class App
{
private WinRTContainer _container;
public App()
{
InitializeComponent();
}
protected override void Configure()
{
_container = new WinRTContainer();
_container.RegisterWinRTServices();
_container.PerRequest<MainViewModel>();
_container.PerRequest<SettingsViewModel>();
ISettingsService settings = _container.RegisterSettingsService();
settings.RegisterCommand<SettingsViewModel>("Test settings");
}
protected override object GetInstance(Type service, string key)
{
var instance = _container.GetInstance(service, key);
if (instance != null) return instance;
throw new Exception("Could not locate any instances.");
}
protected override IEnumerable<object> GetAllInstances(Type service)
{
return _container.GetAllInstances(service);
}
protected override void BuildUp(object instance)
{
_container.BuildUp(instance);
}
protected override void PrepareViewFirst(Frame rootFrame)
{
_container.RegisterNavigationService(rootFrame);
}
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
DisplayRootView<MainView>();
}
}
Finally, create folders for Views and ViewModels in the solution add add to them the required items: MainViewModel, SettingsViewModel, MainView, SettingsView. The views just include a TextBlock with some text. MainViewModel derives from Screen, while SettingsViewModel derives from PropertyChangedBase. There is no relevant code in any of them.
When launching the app, I can see the main view; then I open the charms bar and click settings, and I find the label leading to my app settings; when I click it, I get the exception quoted above. Any hint?
You can find a full repro solution here: http://sdrv.ms/18GIMvB .
If you aren't ready to move to the alpha version of CM, you can update Callisto to 1.4.0 via NuGet. That fixed the error for me.
It seems that the new CM release (alpha 2) fixed the issue, so I'm adding some more information here to help other newcomers like me. Here is what I'm doing now:
In app's Configure I have some bootstrap code like:
...
ResourceLoader loader = ResourceLoader.GetForViewIndependentUse("Resources");
ISettingsService settings = _container.RegisterSettingsService();
settings.RegisterFlyoutCommand<ContentSettingsViewModel>(loader.GetString("SettingsContent"));
The ContentSettingsViewModel is a viewmodel for filtering some contents. The string got from resources is the label which will appear in the settings flyout (be sure there is an entry for this string, as passing an empty or null string triggers an exception). This VM is derived from CM Screen as I'm overriding OnActivate and OnDeactivate to load and save settings when the user opens or dismisses the settings page.

MVP Navigation in WinForms

Have been learning about MVP and have tried writing a test app using it in WinForms. I'm struggling to find a well explained example on how to navigate between my forms/views. As an example, the program starts and I want to show a login dialog then go into my main view if the login was successful. At the moment, my Main method looks something like this:
static void Main()
{
var loginView = Injector.Resolve<ILoginView>();
if (loginView.DoLogin() != LoginResult.OK) return;
var mainView = Injector.Resolve<IMainView>();
Application.Run(mainView); // won't work as mainView isn't a form
}
The Injector object is just a wrapper around an IoC tool (currently StructureMap). The thing is, I've read that I shouldn't really be manually creating instances via the Injector as they should really be done via constructor injection.
I've managed to do this up to a point but not when it comes to navigation. I can't think of an elegant way of moving through my views and was wondering if anyone here might shed some light on this? I've read a little on application controllers but have not found an example to show it clearly.
In regards to the navigation question:
I've managed to do this up to a point but not when it comes to
navigation. I can't think of an elegant way of moving through my views
and was wondering if anyone here might shed some light on this? I've
read a little on application controllers but have not found an example
to show it clearly.
Below is a simplified version of a construct I've used. Note that the setup and tear down hooks are called automatically when the NavigateTo method is called. Also, +1 to #AlexBurtsev, as his answer hints at this very same approach.
// Presenter can and should offer common services for the
// subclasses
abstract class Presenter
{
public void Display()
{
OnDisplay();
}
public void Dismiss()
{
OnDismiss();
}
protected virtual OnDisplay() // hook for subclass
{
}
protected virtual OnDismiss() // hook for subclass
{
}
private NavigationManager _navMgr;
internal NavigationMgr NavigationManager
{
get
{
return _navMgr;
}
set
{
_navMgr = value;
}
}
}
// NavigationManager is used to transition (or navigate)
// between views
class NavigationManager
{
Presenter _current;
// use this override if your Presenter are non-persistent (transient)
public void NavigateTo(Type nextPresenterType, object args)
{
Presenter nextPresenter = Activator.CreateInstance(nextPresenterType);
NavigateTo(nextPresenter);
}
// use this override if your Presenter are persistent (long-lived)
public void NavigateTo(Presenter nextPresenter, object args)
{
if (_current != null)
{
_current.Dismiss()
_current.NavigationMgr = null;
_current = null;
}
if (nextPresenter != null)
{
_current = nextPresenter;
_current.NavigationMgr = this;
_current.Display(args);
}
}
}
class MainMenuPresenter : Presenter
{
private IMainMenuView _mainMenuView = null;
// OnDisplay is your startup hook
protected override void OnDisplay()
{
// get your view from where ever (injection, etc)
_mainMenuView = GetView();
// configure your view
_mainMenuView.Title = GetMainTitleInCurrentLanguage();
// etc
// etc
// listen for relevent events from the view
_mainMenuView.NewWorkOrderSelected += new EventHandler(MainMenuView_NewWorkOrderSelected);
// display to the user
_mainMenuView.Show();
}
protected override void OnDismiss()
{
// cleanup
_mainMenuView.NewWorkOrderSelected -= new EventHandler(MainMenuView_NewWorkOrderSelected);
_mainMenuView.Close();
_mainMenuView = null;
}
// respond to the various view events
private void MainMenuView_NewWorkOrderSelected(object src, EventArgs e)
{
// example of transitioning to a new view here...
NavigationMgr.NavigateTo(NewWorkOrderPresenter, null);
}
}
class NewWorkOrderPresenter : Presenter
{
protected override void OnDisplay()
{
// get the view, configure it, listen for its events, and show it
}
protected override void OnDismiss()
{
// unlisten for events and release the view
}
}
I haven't used WinForms for a long time, but I'll try to answer this. I would use the same strategy as WPF Prism do.
About MainView and Application.Run:
Create a main Region (root Form), with empty container inside which can hold UserControl (I forgot exact class names), then when you need to switch root view, you do RootView.SetView(UserControl view) which will do something like Form.Clear(), Form.AddChild(view).
About the navigation and using container:
You could create a service for navigation: INavigationService which you inject in constructors with method like INavigationService.NavigateView(String(or Type) viewName, params object[] additionalData)
You can insert a method in mainView that returns the actual form.Then you can call
Mainview:IMainView
{
Form GetView()
{
//return new Form();
}
}
In Main you can call ,
Application.Run(mainView.GetView())

Categories

Resources