Xamarian.Form default MasterDetail Project Application.Current.MainPage is null - c#

I'm really trying to work my way through a Xamarian.Form app an I'm finding it difficult because the template out of the box doesn't seem to work.
Basically on the menu I'm trying to nav to the Browse or About page.
however MainPage RootPage { get => Application.Current.MainPage as MainPage; } is returning null.
I've made no changes to this template but I do understand C# so I roughly understand the issue but I'm not aware as to why this is returning null, certainly from the starting template.
MenuPage.xaml.xs
using ProspectGator.Models;
using System;
using System.Collections.Generic;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace ProspectGator.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MenuPage : ContentPage
{
MainPage RootPage { get => Application.Current.MainPage as MainPage; }
List<HomeMenuItem> menuItems;
public MenuPage()
{
InitializeComponent();
menuItems = new List<HomeMenuItem>
{
new HomeMenuItem {Id = MenuItemType.Browse, Title="Browse" },
new HomeMenuItem {Id = MenuItemType.About, Title="About" }
};
ListViewMenu.ItemsSource = menuItems;
ListViewMenu.SelectedItem = menuItems[0];
ListViewMenu.ItemSelected += async (sender, e) =>
{
if (e.SelectedItem == null)
return;
var id = (int)((HomeMenuItem)e.SelectedItem).Id;
await RootPage.NavigateFromMenu(id);
};
}
}
}
App.xaml.cs
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using ProspectGator.Views;
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace ProspectGator
{
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new NavigationPage( new MainPage());
}
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
}
}
}
Typically I would expect this property to be set or already set but I'm not sure. I do have a MainPage.xaml.

Related

Opening a pdf in webview needs more than 5 clicks or no load

I'm trying to open pdf with a webview but some pdf says "No Preview Avaliable", or you have to give it many clicks to open it or directly some crash the app.
Im using the web https://www.pdfpdf.com/samples.html and the first 5 pdfs work fine although sometimes I have to click them 5 times to open them. With those of the last sections, the app crashes when I click on one of them.
The following code can work if I open the pdf in WebView directly .
This is my code:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
x:Class="webviewproblema.MainPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<StackLayout>
<WebView
x:Name="Browser"
HeightRequest="1000"
Navigating="Browser_Navigating"
Source="{Binding HTMLContent}"
WidthRequest="1000" />
</StackLayout>
</ContentPage>
public partial class MainPage : ContentPage
{
public string HTMLContent { get; set; }
public MainPage()
{
InitializeComponent();
Browser.Source = "https://www.pdfpdf.com/samples.html";
}
private void Browser_Navigating(object sender, WebNavigatingEventArgs e)
{
// With this,the app crash
//string url = "https://docs.google.com/gview?embedded=true&url=" + System.Net.WebUtility.UrlEncode(e.Url);
Browser.IsVisible = true;
string url = e.Url;
if ( e.Url.EndsWith(".pdf") || e.Url.EndsWith(".PDF") && !e.Url.Contains("drive.google.com"))
{
Browser.Source = "https://drive.google.com/viewerng/viewer?embedded=true&url=" + url;
}
}
}
You could use custom renderer to open external link in a website .
In forms
Create a custom webview
public class MyWebView : WebView
{
public static readonly BindableProperty UriProperty = BindableProperty.Create(propertyName: "Uri",
returnType: typeof(string),
declaringType: typeof(MyWebView),
defaultValue: default(string));
public string Uri
{
get { return (string)GetValue(UriProperty); }
set { SetValue(UriProperty, value); }
}
}
in Android project
using Android.Content;
using Android.Net.Http;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Webkit;
using Android.Widget;
using App32;
using App32.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(MyWebView), typeof(CustomWebViewRenderer))]
namespace App32.Droid
{
public class CustomWebViewRenderer : WebViewRenderer
{
Context _context;
public CustomWebViewRenderer(Context context) : base(context)
{
_context = context;
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
Android.Webkit.WebView web_view = new Android.Webkit.WebView(_context);
web_view.LoadUrl(((MyWebView)Element).Uri);
web_view.SetWebViewClient(new MyWebViewClient());
SetNativeControl(web_view);
Control.Settings.JavaScriptEnabled = true;
}
}
}
public class MyWebViewClient : WebViewClient
{
public override void OnReceivedSslError(Android.Webkit.WebView view, SslErrorHandler handler, SslError error)
{
handler.Proceed();
}
public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, IWebResourceRequest request)
{
var url = request.Url.ToString();
if (request.Url.ToString().EndsWith(".pdf") || request.Url.ToString().EndsWith(".PDF") && !request.Url.ToString().Contains("drive.google.com"))
{
view.LoadUrl("https://drive.google.com/viewerng/viewer?embedded=true&url=" + request.Url.ToString());
view.SetWebViewClient(new MyWebViewClient());
}
return true;
}
}
}
in iOS project
using System;
using App32;
using App32.iOS;
using Foundation;
using ObjCRuntime;
using UIKit;
using WebKit;
using Xamarin.Forms.Platform.iOS;
[assembly: Xamarin.Forms.ExportRenderer(typeof(MyWebView), typeof(MyWebViewRenderer))]
namespace App32.iOS
{
public class MyWebViewRenderer : ViewRenderer<MyWebView, WKWebView>
{
WKWebView _wkWebView;
protected override void OnElementChanged(ElementChangedEventArgs<MyWebView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
var config = new WKWebViewConfiguration();
_wkWebView = new WKWebView(Frame, config);
_wkWebView.NavigationDelegate = new MyDelegete();
SetNativeControl(_wkWebView);
}
if(e.NewElement!=null)
{
var webview = Element as MyWebView;
var url = webview.Uri;
if (url.EndsWith(".pdf") || url.EndsWith(".PDF") && !url.Contains("drive.google.com"))
{
Control.LoadRequest(new NSUrlRequest(new NSUrl("https://drive.google.com/viewerng/viewer?embedded=true&url=" + webview.Uri)));
}
else
{
Control.LoadRequest(new NSUrlRequest(new NSUrl(webview.Uri)));
}
}
}
}
public class MyDelegete :WKNavigationDelegate
{
public override void DecidePolicy(WKWebView webView, WKNavigationAction navigationAction, WKWebpagePreferences preferences, Action<WKNavigationActionPolicy, WKWebpagePreferences> decisionHandler)
{
// base.DecidePolicy(webView, navigationAction, preferences, decisionHandler);
var url = navigationAction.Request.Url.ToString();
if (url.EndsWith(".pdf") || url.EndsWith(".PDF") && !url.Contains("drive.google.com"))
{
webView.LoadRequest(new NSUrlRequest(new NSUrl("https://drive.google.com/viewerng/viewer?embedded=true&url=" + url)));
}
decisionHandler.Invoke(WKNavigationActionPolicy.Allow, preferences);
}
}
}
in xaml
Now you can use it in xaml like
<StackLayout>
<local:MyWebView x:Name="Browser" Uri="https://xxx" HeightRequest="1000" WidthRequest="1000" />
</StackLayout>

Application with Chrome-Style Tabs using EasyTabs in WinForms

I am trying to create a C# Application with Chrome-Style Tabs using EasyTabs in WinForms, but I am getting the following error code:
The designer must create an instance of type 'EasyTabs.TitleBarTabs' but it cannot because the type is declared as abstract.
I have followed the Youtube-tutorial beneath as a guideline.
https://www.youtube.com/watch?v=WVFjegJK8EY
Code:
using System;
using EasyTabs;
namespace WindowsFormsApp1
{
public partial class AppContainer : TitleBarTabs
{
public AppContainer()
{
InitializeComponent();
AeroPeekEnabled = true;
TabRenderer = new ChromeTabRenderer(this);
}
public override TitleBarTab CreateTab()
{
return new TitleBarTab(this)
{
Content = Form1
{
Text = "New Tab"
}
};
}
private void AppContainer_Load(object sender, EventArgs e)
{
}
}
}
It is normal to see this error when you try to view AppContainer.cs directly.
The designer must create an instance of type 'EasyTabs.TitleBarTabs' but it cannot because the type is declared as abstract.
Let that not deter you from achieving what you wanted to achieve. Ignore the error and simply right click on AppContainer.cs and select View Code
using EasyTabs;
namespace WindowsFormsApp1
{
public partial class AppContainer : TitleBarTabs
{
public AppTabs()
{
InitializeComponent();
AeroPeekEnabled = true;
TabRenderer = new ChromeTabRenderer(this);
Icon = mBible.Properties.Resources.appico;
}
public override TitleBarTab CreateTab()
{
return new TitleBarTab(this)
{
Content = new Form1
{
Text = "New Tab"
}
};
}
}
}
That should be enough to generate new tabs for you.
Now to create tabs easily lets assume you have a form 'MainForm' and the tab you want to be generating is 'Form1' here is what we do
using System;
using System.Windows.Forms;
using EasyTabs;
namespace WindowsFormsApp1
{
public partial class MainForm : Form
{
public static AppContainer tabbedApp = new AppContainer();
public MainForm()
{
InitializeComponent();
}
private void Button1_Click(object sender, EventArgs e)
{
tabbedApp.Tabs.Add(new TitleBarTab(tabbedApp)
{
Content = new Form1
{
Text = "New Tab"
}
});
tabbedApp.SelectedTabIndex = 0;
TitleBarTabsApplicationContext applicationContext = new TitleBarTabsApplicationContext();
applicationContext.Start(tabbedApp);
this.Hide();
}
}
}
You can always add to your tabs a new tab easily by calling this code on another form
AppContainer.tabbedApp.Tabs.Add(new TitleBarTab(AppContainer.tabbedApp)
{
Content = new Form2 { Text = "Another Tab" }
});
AppContainer.tabbedApp.SelectedTabIndex = 0;
I hope that helps and anyone looking for help on similar issues.

When using Prism to DeepLink to a row inside a ListView, how can I update the ListView scroll and highlight?

I am using Xamarin Forms with Prism, based on this GitHub sample..
Desired Behavior
Deep link is clicked, showing the detail view:
User presses back button. Scroll and highlight the linked selection (not happening).
None of the OnNavigation events are firing. Is this a bug? How do I accomplish this?
App.Xaml
public partial class App : PrismApplication
{
public App(IPlatformInitializer initializer = null) : base(initializer) { }
protected override async void OnInitialized()
{
InitializeComponent();
await NavigationService.NavigateAsync("MainTabbedPage/NavigationPage/ShowsListPage/DetailPage?show=279121");
//await NavigationService.NavigateAsync("MainTabbedPage/NavigationPage/ShowsListPage");
}
protected override void RegisterTypes()
{
Container.RegisterTypeForNavigation<UpcomingShowsPage>();
Container.RegisterTypeForNavigation<ShowsListPage>(); // <-- Problematic ListView
Container.RegisterTypeForNavigation<DetailPage>();
Container.RegisterTypeForNavigation<MainTabbedPage>();
Container.RegisterTypeForNavigation<NavigationPage>();
Container.RegisterType<ITsApiService, TsApiService>();
}
ShowsListPage.xaml
ContentPage is using the Prism directive: prism:ViewModelLocator.AutowireViewModel="True". (nothing special)
ShowsListPageViewModel.cs
using System.Collections.ObjectModel;
using InfoSeries.Core.Models;
using InfoSeries.Core.Services;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Navigation;
using Xamarin.Forms;
namespace DeepNavigation.ViewModels
{
public class ShowsListPageViewModel : BindableBase, INavigationAware
{
private readonly ITsApiService _tsApiService;
private readonly INavigationService _navigationService;
private ObservableCollection<SerieFollowersVM> _highlightSeries;
public ObservableCollection<SerieFollowersVM> HighlightSeries
{
get { return _highlightSeries; }
set { SetProperty(ref _highlightSeries, value); }
}
public ShowsListPageViewModel(ITsApiService tsApiService, INavigationService navigationService)
{
_tsApiService = tsApiService;
_navigationService = navigationService;
}
public void OnNavigatedFrom(NavigationParameters parameters)
{
}
public async void OnNavigatedTo(NavigationParameters parameters)
{
var series = await _tsApiService.GetStatsTopSeries();
HighlightSeries = new ObservableCollection<SerieFollowersVM>(series);
}
public void OnNavigatingTo(NavigationParameters parameters)
{
}
private DelegateCommand<ItemTappedEventArgs> _goToDetailPage;
public DelegateCommand<ItemTappedEventArgs> GoToDetailPage
{
get
{
if (_goToDetailPage == null)
{
_goToDetailPage = new DelegateCommand<ItemTappedEventArgs>(async selected =>
{
NavigationParameters param = new NavigationParameters();
var serie = selected.Item as SerieFollowersVM;
param.Add("show", serie.Id);
await _navigationService.NavigateAsync("DetailPage", param);
});
}
return _goToDetailPage;
}
}
}
}
Question
How can I get the back button to select the list view?
Is there any platform guidance saying that the back button after a deep link must go to the source calling application.. rendering this question useless? (e.g. pop the navigation back to Chrome/Safari)

Xamarin forms PopModalAsync doesn't trigger

I'm building a Xamarin.Forms application with a facebook login using Xamarin.Auth.
Entry point (app.cs):
public App()
{
MainPage = new WelcomePage();
}
WelcomePage:
using System;
using Xamarin.Forms;
namespace Project
{
public class WelcomePage : ContentPage
{
public WelcomePage()
{
var login = new Button { Text = "Login" };
login.Clicked += (sender, e) =>
{
Navigation.PushModalAsync(new LoginPage());
};
Content = new StackLayout
{
BackgroundColor = Color.FromHex("F0C640"),
Padding = new Thickness(10, 40, 10, 10),
Children = {
new Label { Text = "Please login" },
login
}
};
}
}
}
LoginPage:
using Xamarin.Forms;
namespace Project
{
public class LoginPage : ContentPage
{
}
}
This is empty as I use Xamarin.Auth to authenticate with facebook so I created 2 different renderers on iOS and Android to display the facebook login page. After the login success I call an action which is located in my app.cs file:
public Action SuccessfulLoginAction
{
get
{
return new Action(() => goToMainPage());
}
}
public void goToMainPage()
{
MainPage.Navigation.PopModalAsync();
//MainPage.Navigation.PopToRootAsync();
MainPage.Navigation.PushAsync(new DetailPage());
}
At the end of the authentication the page is white but I believe it's a white page from Facebook after the authentication is done.
The SuccessfulLoginAction is well called so I go through the goToMainPage() function.
I put some breakpoints and PopModalAsync() doesn't do anything, same for PopToRootAsync() and PushAsync()...
The DetailPage is just a page with a Label. If I try to display it at the beginning of the process (app(){}) it display it well.
Thanks.

Xamarin iOS - this class is not key value coding-compliant for the key NewButton

I seem to be hitting a brick wall when trying to use a component called SideBarNavigation.
I have created a new ViewController in designer and given it a button called NewButton, when I go to load the app it crashes on this line :-
SidebarController = new SidebarNavigation.SidebarController(this, NavController, menuController);
RootViewController.cs
using UIKit;
using SidebarNavigation;
using Inchcape.iOS;
namespace Inchcape.IOS
{
public partial class RootViewController : UIViewController
{
private UIStoryboard _storyboard;
// the sidebar controller for the app
public SidebarNavigation.SidebarController SidebarController { get; private set; }
// the navigation controller
public NavController NavController { get; private set; }
// the storyboard
public override UIStoryboard Storyboard
{
get
{
if (_storyboard == null)
_storyboard = UIStoryboard.FromName("Main", null);
return _storyboard;
}
}
public RootViewController() : base(null, null)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
var introController = (IntroController)Storyboard.InstantiateViewController("IntroController");
var menuController = (MenuViewController)Storyboard.InstantiateViewController("MenuViewController");
// create a slideout navigation controller with the top navigation controller and the menu view controller
NavController = new NavController();
NavController.PushViewController(introController, false);
SidebarController = new SidebarNavigation.SidebarController(this, NavController, menuController);
SidebarController.MenuWidth = 220;
SidebarController.ReopenOnRotate = false;
}
}
}
MenuViewController.cs
using Foundation;
using Inchcape.iOS;
using System;
using UIKit;
namespace Inchcape.iOS
{
[Register("MenuViewController")]
public partial class MenuViewController : BaseController
{
public MenuViewController (IntPtr handle) : base (handle)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
var contentController = (ContentController_)Storyboard.InstantiateViewController("ContentController_");
//ContentButton.TouchUpInside += (o, e) => {
// if (NavController.TopViewController as ContentController == null)
// NavController.PushViewController(contentController, false);
// SidebarController.CloseMenu();
//};
}
}
}
Has anyone experienced this at all???

Categories