Xamarin WPF .NET 5 Displaying WebView2 - c#

I'm trying to display a WebView2 within a Xamarin WPF app on .NET 5.
So at startup I set the MainPage to Navigator which looks like so:
Navigator.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:local="clr-namespace:XamTestNET5.Views"
x:Class="XamTestNET5.Navigator" Title="Here is a title">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackLayout Grid.Row="0" Grid.Column="0" Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Label FontSize="Medium">Hello</Label>
<!--<local:PlaceHolderView></local:PlaceHolderView>-->
<local:CustomWebBrowserView x:Name="browser" Source="https://www.google.com"></local:CustomWebBrowserView>
</StackLayout>
<StackLayout Grid.Row="1" Grid.Column="0" Orientation="Horizontal" HorizontalOptions="FillAndExpand" BackgroundColor="{StaticResource Primary}">
<Button FontSize="Large" Text="Tab 1" BorderWidth="0" BorderColor="Transparent"></Button>
<Button FontSize="Large" Text="Tab 2" BorderWidth="0" BorderColor="Transparent"></Button>
<Button FontSize="Large" Text="Tab 3" BorderWidth="0" BorderColor="Transparent"></Button>
</StackLayout>
</Grid>
</ContentPage>
CustomWebBrowserView.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="XamTestNET5.Views.CustomWebBrowserView">
<ContentView.Content>
<Grid></Grid>
</ContentView.Content>
</ContentView>
CustomWebBrowserView.xaml.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace XamTestNET5.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CustomWebBrowserView : ContentView
{
public static readonly BindableProperty SourceProperty = BindableProperty.Create(
propertyName: "Source",
returnType: typeof(string),
declaringType: typeof(string),
defaultValue: "");
public string Source
{
get { return (string)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
public CustomWebBrowserView()
{
InitializeComponent();
}
}
}
WebBrowserRenderer.cs in the WPF project:
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.Wpf;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms.Platform.WPF;
using XamTestNET5.Views;
using XamTestNET5WPF.Renderers;
[assembly: ExportRenderer(typeof(CustomWebBrowserView), typeof(WebBrowserRenderer))]
namespace XamTestNET5WPF.Renderers
{
public class WebBrowserRenderer : ViewRenderer<CustomWebBrowserView, WebView2>
{
WebView2 webView;
CoreWebView2EnvironmentOptions options = new CoreWebView2EnvironmentOptions();
CoreWebView2Environment env;
String userDataFolder = Path.GetTempPath();
public WebBrowserRenderer() : base()
{
}
private void WebView_CoreWebView2Ready(object sender, EventArgs e)
{
this.webView.CoreWebView2.Navigate(#"https://www.bing.com");
}
protected async override void OnElementChanged(ElementChangedEventArgs<CustomWebBrowserView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
webView = new WebView2();
env = await CoreWebView2Environment.CreateAsync("", userDataFolder, options);
webView.CoreWebView2Ready += WebView_CoreWebView2Ready;
webView.Source = new Uri(#"https://www.bing.com");
webView.Visibility = System.Windows.Visibility.Visible;
this.SetNativeControl(webView);
await webView.EnsureCoreWebView2Async(env);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == nameof(CustomWebBrowserView.SourceProperty))
{
this.webView.Source = new Uri(Element.Source);
this.webView.CoreWebView2.Navigate(Element.Source);
}
}
}
}
I can see by debugging that I'm getting the WebView2 but it obliterates the content page leaving only the title.
If I comment out the CustomWebBrowserView and put in a PlaceHolderView stub, which just looks 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="XamTestNET5.Views.PlaceHolderView">
<ContentView.Content>
<StackLayout>
<Label Text="Placeholder" />
</StackLayout>
</ContentView.Content>
</ContentView>
The layout at least isn't obliterated, but of course no WebView2.
I can't get Shell to work right either but that's to be expected: https://github.com/xamarin/Xamarin.Forms/issues/7377
So I thought that the workaround in the meantime might be just to create my own custom navigation within the app, but I want to provide WebView2 controls in WPF. Am I doing something wrong in the WebBrowserRenderer or Xaml?

Change CustomWebBrowserView to the following, basing off of View rather than ContentView and everything is working now with no obliteration of the view:
CustomWebBrowserView.Xaml:
<?xml version="1.0" encoding="UTF-8"?>
<View xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamTestNET5.Views.CustomWebBrowserView">
</View>
CustomWebBrowserView.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace XamTestNET5.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CustomWebBrowserView : View
{
public static readonly BindableProperty SourceProperty = BindableProperty.Create(
propertyName: "Source",
returnType: typeof(string),
declaringType: typeof(string),
defaultValue: "");
public string Source
{
get { return (string)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
public CustomWebBrowserView()
{
InitializeComponent();
}
}
}
Navigator.xaml:
<StackLayout Grid.Row="0" Grid.Column="0" Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Label FontSize="Medium">Hello</Label>
<!--<local:PlaceHolderView></local:PlaceHolderView>-->
<local:CustomWebBrowserView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" x:Name="browser" Source="https://www.sneauxkones.com"></local:CustomWebBrowserView>
</StackLayout>

Related

Rg.Plugin.PopupPage error with the call line

I installed the plugin on the 3 projects (PCL/Android/IOS)
I am using Xamarin.forms and
The line that calls the popup page shows this error message after the app started:
Unhandled Exception:
System.InvalidOperationException: Platform is not created occurred
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MenuView : ContentPage
{
List<Loja> lstLojas;
IGeolocator locator;
Loja lojaPerto;
Localizacao localizacao;
MyPopupPage s;
public MenuView()
{
s = new MyPopupPage();
InitializeComponent();
CallingGeolocatorAsync();
login();
}
void login()
{
Navigation.PushPopupAsync(s, true);
}
this is my PopUp Page.cs
using System;
using System.Threading.Tasks;
using Rg.Plugins.Popup.Pages;
using Rg.Plugins.Popup.Services;
using Xamarin.Forms;
namespace neoFly_Montana.PopUp
{
public partial class MyPopupPage : PopupPage
{
public MyPopupPage()
{
InitializeComponent();
}
private void OnClose(object sender, EventArgs e)
{
PopupNavigation.PopAsync();
}
protected override Task OnAppearingAnimationEnd()
{
return Content.FadeTo(0.5);
}
protected override Task OnDisappearingAnimationBegin()
{
return Content.FadeTo(1);
}
}
}
this is my popup xml
<?xml version="1.0" encoding="utf-8" ?>
<pages:PopupPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:pages="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup"
xmlns:animations="clr-namespace:Rg.Plugins.Popup.Animations;assembly=Rg.Plugins.Popup"
x:Class="neoFly_Montana.PopUp.MyPopupPage">
<!--Animations use example-->
<pages:PopupPage.Animation>
<animations:ScaleAnimation
PositionIn="Center"
PositionOut="Center"
ScaleIn="1.2"
ScaleOut="0.8"
DurationIn="400"
DurationOut="300"
EasingIn="SinOut"
EasingOut="SinIn"
HasBackgroundAnimation="True"/>
</pages:PopupPage.Animation>
<!-- Content -->
Can someone help?
You can't call that in a contructor...you need to use:
protected override void OnAppearing()
{
base.OnAppearing();
s = new MyPopupPage();
PopupNavigation.PushAsync(s, true);
}
Popuplogin.xaml:
<?xml version="1.0" encoding="UTF-8"?>
<pages:PopupPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="SeralizationApp.Views.Popuplogin"
xmlns:animations="clr-namespace:Rg.Plugins.Popup.Animations;assembly=Rg.Plugins.Popup"
xmlns:pages="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup"
xmlns:myAnimations="clr-namespace:StalizationApp.Animations;assembly=MyProject">
<StackLayout Margin="12"
Padding="24"
Spacing="24"
BackgroundColor="White"
HorizontalOptions="Center"
VerticalOptions="Center">
<StackLayout>
<Label Text="Login" />
<Entry FontSize="30"
Text="Email" />
</StackLayout>
<StackLayout>
<Label Text="ContraseƱa"/>
<Entry FontSize="30"
IsPassword="True"
Text="ContraseƱa" />
</StackLayout>
//enter code here
<Button BackgroundColor="DodgerBlue"
FontSize="30"
Text="Login"
TextColor="White" />
</StackLayout>
</pages:PopupPage>
Popuplogin.cs
using Rg.Plugins.Popup.Pages;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace SeralizationApp.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class Popuplogin : PopupPage // ContentView
{
public Popuplogin ()
{
InitializeComponent ();
}
}
}

xamarin forms web view crashed

work with a web view however1 when I try to work with the web view
the page is crashed and get this error:
"An unhandled exception occured."
attaching my code:
also I want to know if I navagate with the web view to a Image
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="MashamApp.MImageEditor">
<ContentPage.Content>
<StackLayout>
<StackLayout Orientation="Horizontal" Padding="10,10">
<Button Text="Back" HorizontalOptions="StartAndExpand" Clicked="backClicked" />
<Button Text="Forward" HorizontalOptions="End" Clicked="forwardClicked" />
</StackLayout>
<WebView x:Name="Browser" WidthRequest="1000" HeightRequest="1000" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
C#:
using Syncfusion.SfImageEditor.XForms;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace MashamApp
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MImageEditor : ContentPage
{
public MImageEditor()
{
InitializeComponent();
Browser.Source = "http://www.walla.co.il";
}
private void backClicked(object sender, EventArgs e)
{
// Check to see if there is anywhere to go back to
if (Browser.CanGoBack) {
Browser.GoBack ();
} else { // If not, leave the view
Navigation.PopAsync ();
}
}
private void forwardClicked(object sender, EventArgs e)
{
if (Browser.CanGoForward) {
Browser.GoForward ();
}
}
}
}

Background color of selecteditem in listview xamarin.forms

When working with ListView in Xamarin.forms, on selecting an item, the item remains like that with a rather ugly background colour. Can i disable this feature?
Here's my code:
<StackLayout>
<ListView x:Name="FoodList" HasUnevenRows="True" CachingStrategy="RecycleElement" ItemTapped="OnItemTapped">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="0,15,0,0" >
<StackLayout Orientation="Horizontal" BackgroundColor="White" >
<Image Source="{Binding image_url}" Aspect="AspectFill" HeightRequest="200" WidthRequest="200"/>
<StackLayout Orientation="Vertical">
<Label Text="{Binding food_name}" TextColor="Black" Style="{StaticResource MainLisTtext}" />
<Label Text="{Binding price}" TextColor="Black" Style="{StaticResource SubLisTtext}" />
<Label Text="{Binding food_description}" TextColor="Black" Style="{StaticResource SubLisTtext}" />
</StackLayout>
</StackLayout>
</StackLayout>
</ViewCell>vc
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
This can be accomplished by using Custom Renderers
iOS Custom Renderer
Edit the SelectionStyle property on iOS.
Below is an example that sets the UITableViewCellSelectionStyle to None.
using System;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using ListViewSample.iOS;
[assembly: ExportRenderer(typeof(ViewCell), typeof(ViewCellItemSelectedCustomRenderer))]
namespace ListViewSample.iOS
{
public class ViewCellItemSelectedCustomRenderer : ViewCellRenderer
{
public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
{
var cell = base.GetCell(item, reusableCell, tv);
cell.SelectionStyle = UITableViewCellSelectionStyle.None;
return cell;
}
}
}
Android Custom Renderer
Create a new drawable, ViewCellBackground.xml and save it to the Resources>drawable folder:
<?xml version="1.0" encoding="UTF-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" >
<shape android:shape="rectangle">
<!--Change the selected color by modifying this hex value-->
<solid android:color="#FFFFFF" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="#FFFFFF" />
</shape>
</item>
</selector>
Create Custom Renderer for the ViewCell
using System;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using ListViewSample.Droid;
[assembly: ExportRenderer(typeof(ViewCell), typeof(ViewCellItemSelectedCustomRenderer))]
namespace ListViewSample.Droid
{
public class ViewCellItemSelectedCustomRenderer : ViewCellRenderer
{
protected override Android.Views.View GetCellCore(Cell item, Android.Views.View convertView, Android.Views.ViewGroup parent, Android.Content.Context context)
{
var cell = base.GetCellCore(item, convertView, parent, context);
cell.SetBackgroundResource(Resource.Drawable.ViewCellBackground);
return cell;
}
}
}
Edit: Removed implementation without Custom Renderers
Sample Xamarin.Forms ListView App
using System;
using System.Collections.Generic;
using Xamarin.Forms;
namespace ListViewSample
{
public class CustomViewCell : ViewCell
{
public CustomViewCell()
{
View = new Label
{
Text = "Hello World"
};
}
}
public class ListViewContentPage : ContentPage
{
public ListViewContentPage()
{
var itemSourceList = new List<CustomViewCell>();
itemSourceList.Add(new CustomViewCell());
itemSourceList.Add(new CustomViewCell());
var listView = new ListView();
listView.ItemTemplate = new DataTemplate(typeof(CustomViewCell));
listView.ItemsSource = itemSourceList;
listView.SeparatorVisibility = SeparatorVisibility.None;
Content = listView;
}
}
public class App : Application
{
public App()
{
// The root page of your application
MainPage = new NavigationPage(new ListViewContentPage());
}
}
}

How to show data from ASP.NET Web Application to Xamarin.Forms?

I want all the records created in ASP.NET Web Application to be shown in my Mobile App Xamarin.Forms. What's happening to my program is that I was able to create records in my Web Application and save it, but I wasn't able to make it appear in my Xamarin.Forms Mobile app. I have created a MainViewModel that will get the records from the Web Application which I have binded to my MainPage.
These are my codes:
MainPageMain.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:local="clr-namespace:XamarinDemoApp"
x:Class="XamarinDemoApp.MainPageMain"
xmlns:ViewModels="clr-namespace:XamarinDemoApp.ViewModels;assembly=XamarinDemoApp"
BackgroundColor="Teal"
Title=" Title Bar">
<ContentPage.BindingContext>
<ViewModels:MainViewModel/>
</ContentPage.BindingContext>
<StackLayout Orientation="Vertical">
<ListView ItemsSource="{Binding EmployeesList}"
HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Label Text="{Binding Name}"
FontSize="24"/>
<Label Text="{Binding Department}"
FontSize="24"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Label Text="This is the MainPage"/>
</StackLayout>
MainViewModel.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using XamarinDemoApp.Models;
using XamarinDemoApp.Services;
namespace XamarinDemoApp.ViewModels
{
public class MainViewModel : INotifyPropertyChanged
{
private List<Employee> _employeesList;
public List<Employee> EmployeesList
{
get { return _employeesList; }
set
{
_employeesList = value;
OnPropertyChanged();
}
}
public MainViewModel()
{
InitializeDataAsync();
}
private async Task InitializeDataAsync()
{
var employeesServices = new EmployeesServices();
EmployeesList = await employeesServices.GetEmployeesAsync();
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Make a separate API controller that you can use to call EmployeeList as a JSON object. That is the preferred way to do this kind of thing. Example:
public class EmployeeApiController : ApiController
{
[HttpGet]
public async Task<List<Employee>> Get()
{
return await employeesServices.GetEmployeesAsync();
}
}

Carousel - add different pages to Carousel

I am receiving an error - "Carousel has no children".
I utilized the carousel sample from Xamarin. Carousel works if the pages are the same. My requirement is that my pages are different but I want it to work in a carousel.
Page 1 - Image
Page 2 - Buttons
Page 3 - Check Boxes
MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<CarouselPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CarouselApp.MainPage">
<CarouselPage.ItemTemplate>
<DataTemplate>
<ContentPage>
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness" iOS="0,40,0,0" Android="0,40,0,0">
</ContentPage.Padding>
<StackLayout>
<ContentView BindingContext="PageName"></ContentView>
</StackLayout>
</ContentPage>
</DataTemplate>
</CarouselPage.ItemTemplate>
</CarouselPage>
MainPage.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace CarouselApp
{
public partial class MainPage : CarouselPage
{
public MainPage()
{
InitializeComponent();
ItemsSource = CarouselAppDataModel.All;
}
}
}
DataModel
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace CarouselApp
{
public class CarouselDataModel : ContentView
{
public ContentView PageName { get; set; }
public static IList<CarouselDatModel> All { get; set; }
private Carousel03 fl3 as new Carousel03;
private Carousel04 fl4 as new Carousel04;
public CarouselDataDataModel()
{
All = new ObservableCollection<CarouselDataModel>
{
new CarouselDataModel
{
PageName = fl3
},
new CarouselDataModel
{
PageName = fl4
}
};
}
}
}
Since your pages are all different, and you are using XAML... rather than use a data template just create three consecutive content pages in your XAML as below
<CarouselPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CarouselPageNavigation.MainPage">
<ContentPage>
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness" iOS="0,40,0,0" Android="0,40,0,0" />
</ContentPage.Padding>
<StackLayout>
<Label Text="Red" FontSize="Medium" HorizontalOptions="Center" />
<BoxView Color="Red" WidthRequest="200" HeightRequest="200" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
<ContentPage>
...
</ContentPage>
<ContentPage>
...
</ContentPage>
</CarouselPage>

Categories

Resources