.net MAUI, android System.InvalidOperationException: 'Native View not set' on navigation - c#

Can't find source of evil, have two pages, added as Singleton service, when i navigate to the second page for a first time everything great, when i navigate second time i get:
System.InvalidOperationException: 'Native View not set'
MAUI version 6.0.300-rc.2.5513+sha.8a017cf73-azdo.6048189
Emulator Android11 API 30
Tested on Desktop everything seems ok...
MauiProgram.cs
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
builder.Services.AddSingleton<ShellViewModel>();
builder.Services.AddSingleton<AppShell>();
builder.Services.AddSingleton<MainPage>();
builder.Services.AddSingleton<SettingsPage>();
return builder.Build();
}
}
App.xaml - default to new project
App.cs
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new AppShell();
Routing.RegisterRoute(nameof(MainPage), typeof(MainPage));
Routing.RegisterRoute(nameof(SettingsPage), typeof(SettingsPage));
}
}
AppShell.xaml
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
x:Class="MauiAppTest.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MauiAppTest"
xmlns:vm="clr-namespace:MauiAppTest.ViewModels"
x:DataType="vm:ShellViewModel"
Shell.FlyoutBehavior="Disabled">
<Shell.ToolbarItems>
<ToolbarItem Command="{Binding GoToSettings}" Text="Settings"/>
</Shell.ToolbarItems>
<ShellContent
Title="Hello, World!"
ContentTemplate="{DataTemplate local:MainPage}"
Route="MainPage" />
</Shell>
AppShell.cs
public partial class AppShell : Shell
{
public AppShell()
{
InitializeComponent();
BindingContext = new ShellViewModel();
}
}
ShellViewModel.cs
public class ShellViewModel: ObservableObject
{
public AsyncRelayCommand GoToSettings { get; private set; }
public ShellViewModel()
{
GoToSettings = new AsyncRelayCommand(async () => await Shell.Current.GoToAsync("SettingsPage"));
}
}
MainPage and SettingsPage just two default blank pages
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiAppTest.MainPage"
Title="MainPage">
<StackLayout>
<Label Text="Welcome to .NET MAUI!"
VerticalOptions="Center"
HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiAppTest.SettingsPage"
Title="SettingsPage">
<StackLayout>
<Label Text="Welcome to .NET MAUI!"
VerticalOptions="Center"
HorizontalOptions="Center" />
</StackLayout>
</ContentPage>

Related

Shell Navigation

I have a login/register page, and I want to be able to navigate between them routing navigation (//LoginPage) like in a web app. I cant really make it work. I have built a AppShell.xaml page and i have registered my LoginPage and RegisterPage in App.xaml.cs (I have tried registering them in AppShell.xaml.cs too) and I have a viewmodel that has 2 functions for navigating between login and register pages but when I click on the button to navigate I get this
System.NullReferenceException: 'Object reference not set to an instance of an object.'
Here is my view-model
namespace Appointments.ViewModels
{
public class RegLogViewModel : BaseViewModel
{
public AsyncCommand GoToRegisterCommand { get; }
public AsyncCommand GoToLoginCommand { get; }
public RegLogViewModel()
{
GoToLoginCommand = new AsyncCommand(GoToLogin);
GoToRegisterCommand = new AsyncCommand(GoToRegister);
}
async Task GoToRegister()
{
await Shell.Current.GoToAsync($"//{ nameof(RegisterPage)}");
}
async Task GoToLogin()
{
await Shell.Current.GoToAsync($"//{ nameof(LoginPage)}");
}
}
My AppShell.xaml
<Shell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Appointments.AppShell"
xmlns:views="clr-namespace:Appointments.Views">
//// I HAVE TRIED WITH AND WITHOUT THIS SHELLCONTENT\\\\\
<ShellContent Route="LoginPage" ContentTemplate="{DataTemplate views:LoginPage}"/>
<ShellContent Route="RegisterPage" ContentTemplate="{DataTemplate views:RegisterPage}"/>
</Shell>
My AppShell.xaml.cs
namespace Appointments
{
public partial class AppShell : Shell
{
public AppShell()
{
InitializeComponent();
}
}
}
My App.xaml.cs
namespace Appointments
{
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new LoginPage();
}
}
}
And Login.xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewmodels="clr-namespace:Appointments.ViewModels"
x:DataType="viewmodels:RegLogViewModel"
x:Class="Appointments.Views.LoginPage">
<ContentPage.Content>
<StackLayout>
<Label
Text="Login Page!"
FontSize="Title"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
<Label
Text="{Binding Name}"/>
<Entry
Text="{Binding Name}"/>
<Button
Text="Go To Registration"
Command="{Binding GoToRegisterCommand}"/>
<ActivityIndicator IsRunning="{Binding IsBusy, Mode=OneWay}"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
The problem was that in App.xaml.cs I have
MainPage = new LoginPage();
but I had to use
MainPage = new AppShell();
it will work but now I don't understand how the app knows to open my LoginPage first and not RegisterPage or any other page

xamarin mvvmcross TabbedPage inside TabbedPage

How do I easily implement a tabbed page inside a tabbed page in xamarin forms with mvvmcross?
TabbedPage1;
[MvxTabbedPagePresentationAttribute(Position = TabbedPosition.Root, WrapInNavigationPage = true, NoHistory = false)]
public partial class TabbedPage1: MvxTabbedPage<ViewModels.TabbedPage1ViewModel>
{
public TabbedPage1()
{
InitializeComponent();
}
}
TempPage;
[MvxTabbedPagePresentationAttribute(Position = TabbedPosition.Tab, Icon = "map_outline", WrapInNavigationPage = true, NoHistory = false)]
public partial class TempPage: MvxContentPage<ViewModels.TempPageViewModel>
{
public TempPage()
{
InitializeComponent();
}
}
TabbedPage2;
[MvxTabbedPagePresentationAttribute(Position = TabbedPosition.Root, WrapInNavigationPage = true, NoHistory = false)]
public partial class TabbedPage2 : MvxTabbedPage<ViewModels.TabbedPage2ViewModel>
{
public TabbedPage2 ()
{
InitializeComponent();
}
}
my current situation is, that the tabbedpage2 shows like a modal page.
You could nest a TabView in Tabbed page. Install Xam.Plugin.TabView via NuGet. https://www.nuget.org/packages/Xam.Plugin.TabView
Create three tab pages in views folder.
Tabbed Page:
<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage
x:Class="TabbedPageDemo.MainPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:Views="clr-namespace:TabbedPageDemo.Views"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
BarBackgroundColor="Blue"
BarTextColor="White"
mc:Ignorable="d">
<Views:Tab1_Page Title="TAB1" />
<Views:Tab2_Page Title="TAB2" />
<Views:Tab3_Page Title="TAB3" />
</TabbedPage>
And then use TabView in you tab1 page.
Tab1_Page:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
x:Class="TabbedPageDemo.Views.Tab1_Page"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:local="clr-namespace:Xam.Plugin.TabView;assembly=Xam.Plugin.TabView"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<ContentPage.Content>
<local:TabViewControl>
<local:TabViewControl.ItemSource>
<local:TabItem HeaderText="SUBTAB1">
<StackLayout VerticalOptions="Start" Padding="10">
<Button
BackgroundColor="White"
Text="List Item"
TextColor="Black"/>
</StackLayout>
</local:TabItem>
<local:TabItem HeaderText="SUBTAB2">
<Image Source="pink.jpg" />
</local:TabItem>
</local:TabViewControl.ItemSource>
</local:TabViewControl>
</ContentPage.Content>
</ContentPage>
Please note, if you want to make the tabs in tabbed page in the bottom. Add the code below in your MainPage.
On<Android>().SetToolbarPlacement(ToolbarPlacement.Bottom);
You could download the code sample from GitHub in TabbedPage_NestedTabView/TabbedPageDemo
https://github.com/WendyZang/Test.git

Bug? System.ArgumentException: 'unable to figure out route for:

Error
System.ArgumentException: 'unable to figure out route for:
//RegisterPage Parameter name: uri' System.ArgumentException: 'unable
to figure out route for: //LogoPage Parameter name: uri'
What is wrong? It cant figure out the route...?
XAML
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="MyApp.Views.WelcomePage"
Shell.NavBarIsVisible="False">
<ContentPage.Content>
<StackLayout Padding="10,0,10,0" VerticalOptions="Center">
<Button VerticalOptions="Center" Text="Register" Command="{Binding RegisterCommand}"/>
<Button VerticalOptions="Center" Text="Login" Command="{Binding LoginCommand}"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
Code behind
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class WelcomePage : ContentPage
{
public WelcomePage()
{
InitializeComponent();
this.BindingContext = new WelcomeViewModel();
}
}
WelcomeViewModel.cs
public Command RegisterCommand { get; }
public Command LoginCommand { get; }
public WelcomeViewModel()
{
RegisterCommand = new Command(OnRegisterClicked);
LoginCommand = new Command(OnLoginClicked);
}
private async void OnRegisterClicked(object obj)
{
await Shell.Current.GoToAsync($"//{nameof(RegisterPage)}");
}
private async void OnLoginClicked(object obj)
{
await Shell.Current.GoToAsync($"//{nameof(LoginPage)}");
}
Your need to register a route for each page you are willing to navigate into it using Shell.Current.GoToAsync(), with this way you can also clarify your pages hierarchy:
<FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
<ShellContent Title="RegisterPage"
Route="RegisterPage"
ContentTemplate="{DataTemplate local:RegisterPage}"/>
<ShellContent Title="LoginPage"
Route="LoginPage"
ContentTemplate="{DataTemplate local:LoginPage}"/>
<ShellContent Title="Page3"
ContentTemplate="{DataTemplate local:Page3}"/>
</FlyoutItem>
You can also register the route using Routing.RegisterRoute() in the code if you prefer, as long as it runs before a route is invoked:
Routing.RegisterRoute("//Page3", typeof(Page3));
Microsoft Documentation
For more details: Shell Navigation
For my problem, I registered routes behind of ShellPage, It took a while to figure out and add new route to get work.
I am not sure it is the best way to register routes in AppShell.cs
public partial class AppShell : Shell
{
public AppShell()
{
InitializeComponent();
Routing.RegisterRoute(nameof(PartPage), typeof(PartPage));
Routing.RegisterRoute(nameof(DetailPage), typeof(DetailPage));
Routing.RegisterRoute(nameof(PersonPage), typeof(PersonPage));
}
}

Custom control in Xamarin Forms doesn't work

I'm trying to create a custom control of an ImageButton to which I can assign a property that is to give it a color and another an image with Source. I have tried to do it this way but the image and the color that I am giving it does not work for me. This is my code:
View1.xaml.cs:
public partial class View1 : ContentView
{
public static readonly BindableProperty ImageSourceProperty =
BindableProperty.Create("Source", typeof(ImageSource),typeof(ImageButton),default(ImageSource));
public ImageSource Source {
get { return (ImageSource)GetValue(ImageSourceProperty); }
set { SetValue(ImageSourceProperty, value); }
}
//============================================
public static readonly BindableProperty ButtonColorProperty =
BindableProperty.Create("ButtonColor", typeof(Color), typeof(ImageButton), Color.White);
public Color ButtonColor
{
get { return (Color)GetValue(ButtonColorProperty); }
set { SetValue(ButtonColorProperty, value); }
}
public View1()
{
InitializeComponent();
}
}
View1.xaml:
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CustomContro.View1">
<StackLayout>
<ImageButton CornerRadius="20" WidthRequest="70" HeightRequest="70" />
</StackLayout>
</ContentView>
MainPage.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CustomContro.MainPage"
xmlns:local="clr-namespace:CustomContro"
>
<AbsoluteLayout>
<local:View1
Source="dieciseis.png"
ButtonColor="Green"
/>
</AbsoluteLayout>
</ContentPage>
You could try to change like below:
the custom control View1:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class View1 : ContentView
{
public static readonly BindableProperty ImageSourceProperty =
BindableProperty.Create("ImageSource", typeof(ImageSource), typeof(View1), null);
public ImageSource ImageSource
{
get { return (ImageSource)GetValue(ImageSourceProperty); }
set { SetValue(ImageSourceProperty, value); }
}
public static readonly BindableProperty ButtonColorProperty =
BindableProperty.Create("ButtonColor", typeof(Color), typeof(View1), null);
public Color ButtonColor
{
get { return (Color)GetValue(ButtonColorProperty); }
set { SetValue(ButtonColorProperty, value); }
}
public View1()
{
InitializeComponent();
BindingContext = this;
}
}
the View1.xaml:
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="EntryCa.View1">
<ContentView.Content>
<StackLayout>
<ImageButton x:Name="image" CornerRadius="20" WidthRequest="70" HeightRequest="70" Source="{Binding ImageSource}" BackgroundColor="{Binding ButtonColor}" />
</StackLayout>
</ContentView.Content>
</ContentView>
use it like:
<local:View1 ImageSource="dieciseis.png" ButtonColor="Green"></local:View1>
You have to set the values for the ImageButton like this:
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CustomContro.View1"
x:Name="MyAwesomeContentView">
<StackLayout>
<ImageButton CornerRadius="20"
WidthRequest="70"
HeightRequest="70"
ImageSource="{Binding Path=Source, Source={x:Reference MyAwesomeContentView}}"
Color="{Binding Path=ButtonColor, Source={x:Reference MyAwesomeContentView}}"
/>
</StackLayout>
</ContentView>

Activity Indicator while loading WebView Xamarin forms

I want to load an Activity indicator first when the WebView is loading data , then it turns Invisible after loading data.
Below is my Xaml Code:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" Title="Shows Trending" xmlns:o="clr-namespace:Octane.Xam.VideoPlayer;assembly=Octane.Xam.VideoPlayer" x:Class="BBSTV.TrendingShowsDetails">
<ActivityIndicator x:Name="activity_indicator" Color="Blue" />
<WebView VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" x:Name="loadVideo_wv">
</WebView>
</ContentPage>
Below is my C# code:
using System;
using System.Collections.Generic;
using Xamarin.Forms;
namespace BBSTV
{
public partial class TrendingShowsDetails : ContentPage
{
public TrendingShowsDetails(string videolink)
{
InitializeComponent();
activity_indicator.IsRunning = true;
loadVideo_wv.Source = "https://www.youtube.com/playlist?list=" + videolink;
activity_indicator.IsRunning = false;
}
}
}
Try out this :
C# code :
public TrendingShowsDetails(string videolink)
{
InitializeComponent();
loadVideo_wv.Source = "https://www.youtube.com/playlist?list=" + videolink;
}
protected async override void OnAppearing()
{
base.OnAppearing();
await activity_indicator.ProgressTo(0.9, 900, Easing.SpringIn);
}
public void OnNavigating(object sender, WebNavigatingEventArgs e)
{
activity_indicator.IsVisible = true;
}
public void OnNavigated(object sender, WebNavigatedEventArgs e)
{
activity_indicator.IsVisible = false;
}
Xaml Code:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
Title="Shows Trending" xmlns:o="clr-namespace:Octane.Xam.VideoPlayer;assembly=Octane.Xam.VideoPlayer" x:Class="BBSTV.TrendingShowsDetails">
<StackLayout>
<ProgressBar Progress="0.2" IsVisible="false" HorizontalOptions="FillAndExpand" x:Name="activity_indicator" />
<WebView VerticalOptions="FillAndExpand" Navigating="OnNavigating" Navigated="OnNavigated" HorizontalOptions="FillAndExpand" x:Name="loadVideo_wv">
</WebView>
</StackLayout>
</ContentPage>
This question is already answered here:
https://forums.xamarin.com/discussion/59056/how-to-get-the-progress-of-webview-while-loading-the-data-xamarin-forms
and here:
Xamarin.Forms.WebView initial loading indicator

Categories

Resources