I'm creating a PieChart using OxyPlot here in my Xamarin.Forms (Portable) Application. I created a ViewModel named PieViewModel where in I declare the content of the Pie Chart. In my SalesPage.XAML.cs, I call the ViewModel and access the salesmodel in it. In my XAML code, I bind the salesmodel in my code.
However, I wasn't able to display the PieChart. Here are the codes I used:
PieViewModel.cs
using OxyPlot;
using OxyPlot.Series;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace XamarinFormsDemo.ViewModels
{
public class PieViewModel : INotifyPropertyChanged
{
private PlotModel modelP1;
public PieViewModel()
{
modelP1 = new PlotModel { Title = "Pie Sample1" };
dynamic seriesP1 = new PieSeries { StrokeThickness = 2.0, InsideLabelPosition = 0.8, AngleSpan = 360, StartAngle = 0 };
seriesP1.Slices.Add(new PieSlice("Africa", 1030) { IsExploded = false, Fill = OxyColors.PaleVioletRed });
seriesP1.Slices.Add(new PieSlice("Americas", 929) { IsExploded = true });
seriesP1.Slices.Add(new PieSlice("Asia", 4157) { IsExploded = true });
seriesP1.Slices.Add(new PieSlice("Europe", 739) { IsExploded = true });
seriesP1.Slices.Add(new PieSlice("Oceania", 35) { IsExploded = true });
modelP1.Series.Add(seriesP1);
}
public PlotModel Model1
{
get { return modelP1; }
set { modelP1 = value; }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
.
SalesPage.XAML.cs
using OxyPlot;
using OxyPlot.Xamarin.Forms;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XamarinFormsDemo.ViewModels;
using Xamarin.Forms;
namespace XamarinFormsDemo.Views
{
public partial class SalesPage : ContentPage
{
public SalesPage()
{
}
}
}
.
SalesPage.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:oxy="clr-namespace:OxyPlot.Xamarin.Forms;assembly=OxyPlot.Xamarin.Forms"
xmlns:ViewModels="clr-namespace:XamarinFormsDemo.ViewModels;assembly=XamarinFormsDemo"
x:Class="XamarinFormsDemo.Views.SalesPage"
BackgroundImage="bg3.jpg"
Title="Sales Page">
<oxy:PlotView Model="{Binding Model1}" VerticalOptions="Center" HorizontalOptions="Center"/>
</ContentPage>
.
MainActivity.cs
using System;
using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using ImageCircle.Forms.Plugin.Droid;
using Xamarin.Forms.Platform.Android;
namespace XamarinFormsDemo.Droid
{
[Activity(Label = "XamarinFormsDemo", Icon = "#drawable/recordsicon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : AndroidActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
OxyPlot.Xamarin.Forms.Platform.Android.PlotViewRenderer.Init();
LoadApplication(new App());
ImageCircleRenderer.Init();
}
}
}
Please help me with this. I'm really getting confused on how the things are going. Thanks a lot.
Here's some sample code:
App: (Portable)
public class App : Application
{
public App()
{
MainPage = new Page3();
}
}
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:oxy="clr-namespace:OxyPlot.Xamarin.Forms;assembly=OxyPlot.Xamarin.Forms"
x:Class="App26.Page3">
<ContentPage.Content>
<oxy:PlotView Model="{Binding MyModel}"></oxy:PlotView>
</ContentPage.Content>
</ContentPage>
CS:
public partial class Page3 : ContentPage
{
public MyViewModel vm { get; set; }
public Page3()
{
InitializeComponent();
vm = new MyViewModel();
BindingContext = vm;
}
}
ViewModel:
public class MyViewModel
{
public PlotModel MyModel { get; set; }
public MyViewModel()
{
PieSeries pieSeries = new PieSeries();
pieSeries.Slices.Add(new PieSlice("Africa", 1030) { IsExploded = false, Fill = OxyColors.PaleVioletRed });
pieSeries.Slices.Add(new PieSlice("Americas", 929) { IsExploded = true });
pieSeries.Slices.Add(new PieSlice("Asia", 4157) { IsExploded = true });
pieSeries.Slices.Add(new PieSlice("Europe", 739) { IsExploded = true });
pieSeries.Slices.Add(new PieSlice("Oceania", 350) { IsExploded = true });
MyModel = new PlotModel();
MyModel.Series.Add(pieSeries);
}
}
MainActivity: (Droid)
[Activity(Label = "App26", Icon = "#drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
OxyPlot.Xamarin.Forms.Platform.Android.PlotViewRenderer.Init();
LoadApplication(new App());
}
}
Related
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>
In xamarin.forms the timepicker defaults to a clock view. I would like to use the spinner version since this fits better for the end user.
I tried this in my .xaml file
<?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"
xmlns:system="clr-namespace:System;assembly=netstandard"
mc:Ignorable="d"
x:Class="namespace.Pages.HoursWorkedPage">
<ContentPage.Content>
<StackLayout>
<DatePicker
MinimumDate="{Binding Source=(system:DateTime.Now())}"
DateSelected="DatePick er_DateSelected"/>
<TimePicker
Format="T"
android:timePickerMode="spinner"/>
Time="{Binding Source=(system:DateTime.Now.TimeOfDay())}"
PropertyChanging="OnTimeChanged"
SpinnerFormatString="t"
</StackLayout>
</ContentPage.Content>
</ContentPage>
But it give me a the error that android is not part of contentpage.
I have been looking all over the internet but I can't seem to get it fixed.
Do you want to achieve the result like following gif?
If so, you should create a custom renderer for your timePicker.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using App3.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(Xamarin.Forms.TimePicker), typeof(MyTimePicker))]
namespace App3.Droid
{
public class MyTimePicker : TimePickerRenderer
{
public MyTimePicker(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.TimePicker> e)
{
base.OnElementChanged(e);
TimePickerDialogIntervals timePickerDlg = new TimePickerDialogIntervals(this.Context, new EventHandler<TimePickerDialogIntervals.TimeSetEventArgs>(UpdateDuration),
Element.Time.Hours, Element.Time.Minutes, true);
var control = new EditText(this.Context);
control.Focusable = false;
control.FocusableInTouchMode = false;
control.Clickable = false;
control.Click += (sender, ea) => timePickerDlg.Show();
control.Text = Element.Time.Hours.ToString("00") + ":" + Element.Time.Minutes.ToString("00");
SetNativeControl(control);
}
void UpdateDuration(object sender, Android.App.TimePickerDialog.TimeSetEventArgs e)
{
Element.Time = new TimeSpan(e.HourOfDay, e.Minute, 0);
Control.Text = Element.Time.Hours.ToString("00") + ":" + Element.Time.Minutes.ToString("00");
}
}
public class TimePickerDialogIntervals : TimePickerDialog
{
public const int TimePickerInterval = 15;
private bool _ignoreEvent = false;
public TimePickerDialogIntervals(Context context, EventHandler<TimePickerDialog.TimeSetEventArgs> callBack, int hourOfDay, int minute, bool is24HourView)
: base(context, TimePickerDialog.ThemeHoloLight, (sender, e) =>
{
callBack(sender, new TimePickerDialog.TimeSetEventArgs(e.HourOfDay, e.Minute * 5));
}, hourOfDay, minute / TimePickerInterval, is24HourView)
{
}
protected TimePickerDialogIntervals(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
}
public override void SetView(Android.Views.View view)
{
SetupMinutePicker(view);
base.SetView(view);
}
void SetupMinutePicker(Android.Views.View view)
{
var numberPicker = FindMinuteNumberPicker(view as ViewGroup);
if (numberPicker != null)
{
numberPicker.MinValue = 0;
numberPicker.MaxValue = 11;
numberPicker.SetDisplayedValues(new String[] { "00", "05", "10", "15", "20", "25", "30", "35", "40", "45", "50", "55" });
}
}
protected override void OnCreate(Android.OS.Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
GetButton((int)DialogButtonType.Negative).Visibility = Android.Views.ViewStates.Gone;
this.SetCanceledOnTouchOutside(false);
}
private NumberPicker FindMinuteNumberPicker(ViewGroup viewGroup)
{
for (var i = 0; i < viewGroup.ChildCount; i++)
{
var child = viewGroup.GetChildAt(i);
var numberPicker = child as NumberPicker;
if (numberPicker != null)
{
if (numberPicker.MaxValue == 59)
{
return numberPicker;
}
}
var childViewGroup = child as ViewGroup;
if (childViewGroup != null)
{
var childResult = FindMinuteNumberPicker(childViewGroup);
if (childResult != null)
return childResult;
}
}
return null;
}
}
}
On My project, I worked on Xamarin.forms and Xamarin.android. All the pages in Xamarin.forms work fine, but when I click on the button that should directs to an activity in Xamarin.forms, it shows nothing.
My code is shown below, I wanted to show the content that is in NewViewRenderer in Xamarin.Forms
** Xamarin.forms:
MainPage.xaml ( it has the bellow button that shows RegionPage.xaml)
...
<StackLayout Grid.Row="2" Grid.Column="1" Orientation="Vertical">
<Image Source="location.png"
Grid.Row="2"
Grid.Column="1"
BackgroundColor="White"
WidthRequest="60" HeightRequest="60"
>
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped_5"/>
</Image.GestureRecognizers>
</Image>
<Label Text="Regions" HorizontalTextAlignment="Center" />
</StackLayout>
....
NewView.cs
using ...
namespace miemss_xamarin
{public class NewView : View{}}
RegionPage.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" xmlns:local="clr-namespace:miemss_xamarin;assembly=miemss_xamarin"
mc:Ignorable="d"
Title="Regions"
x:Class="miemss_xamarin.RegionPage">
<ContentPage.Content>
<local:NewView />
</ContentPage.Content>
</ContentPage>
In the android, I've my layout (NotificationLayout.xml)like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:text="Message Notifications for:"
android:id="#+id/msgText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMediumInverse"
android:padding="10dp"
android:textColor="#android:color/black"
/>
<Switch
android:id="#+id/SubscribeToRegion1"
android:text="Region 1"
android:textAppearance="?android:attr/textAppearanceMediumInverse"
android:padding="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/> ... (and 4 other Switches)
NewViewRenderer.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Firebase.Messaging;
using miemss_xamarin.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(miemss_xamarin.NewView), typeof(NewViewRenderer))]
namespace miemss_xamarin.Droid
{
public class NewViewRenderer : ViewRenderer <miemss_xamarin.NewView,miemss_xamarin.Droid.NewViewRenderer>
{
NewViewRenderer newViewRenderer;
Android.Widget.Switch btnRegion1; Android.Widget.Switch btnRegion2; Android.Widget.Switch btnRegion3; Android.Widget.Switch btnRegion4; Android.Widget.Switch btnRegion5;
public NewViewRenderer (Context context):base (context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<miemss_xamarin.NewView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
// var context = new NewViewRenderer(Forms.Context);
//SetNativeControl(context);
var context = Android.App.Application.Context;
LayoutInflater minflater = context.GetSystemService(Context.LayoutInflaterService) as LayoutInflater;
var view = minflater.Inflate(Resource.Layout.NotificationLayout, this, false);
var msgText = view.FindViewById<TextView>(Resource.Id.msgText);
btnRegion1 = view.FindViewById<Android.Widget.Switch>(Resource.Id.SubscribeToRegion1);
btnRegion2 = view.FindViewById<Android.Widget.Switch>(Resource.Id.SubscribeToRegion2);
btnRegion3 = view.FindViewById<Android.Widget.Switch>(Resource.Id.SubscribeToRegion3);
btnRegion4 = view.FindViewById<Android.Widget.Switch>(Resource.Id.SubscribeToRegion4);
btnRegion5 = view.FindViewById<Android.Widget.Switch>(Resource.Id.SubscribeToRegion5);
// base.SetNativeControl(view);
It always shows red underline under view, so I
}
if (e.NewElement != null)
{
btnRegion1.CheckedChange += (a, b) =>
{
bool isChecked = b.IsChecked;
if (isChecked)
FirebaseMessaging.Instance.SubscribeToTopic("R1");
else
FirebaseMessaging.Instance.UnsubscribeFromTopic("R1");
};
btnRegion2.CheckedChange += (c, d) =>
{
bool isChecked = d.IsChecked;
if (isChecked)
FirebaseMessaging.Instance.SubscribeToTopic("R2");
else
FirebaseMessaging.Instance.UnsubscribeFromTopic("R2");
};
btnRegion3.CheckedChange += (e, f) =>
{
bool isChecked = f.IsChecked;
if (isChecked)
FirebaseMessaging.Instance.SubscribeToTopic("R3");
else
FirebaseMessaging.Instance.UnsubscribeFromTopic("R3");
};
btnRegion4.CheckedChange += (g, h) =>
{
bool isChecked = h.IsChecked;
if (isChecked)
FirebaseMessaging.Instance.SubscribeToTopic("R4");
else
FirebaseMessaging.Instance.UnsubscribeFromTopic("R4");
};
btnRegion5.CheckedChange += (i, j) =>
{
bool isChecked = j.IsChecked;
if (isChecked)
FirebaseMessaging.Instance.SubscribeToTopic("R5");
else
FirebaseMessaging.Instance.UnsubscribeFromTopic("R5");
};
}
}
and no changes on the MainActivity.cs (Default code) as shown below:
using System;
using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Util;
using Firebase.Iid;
using Android.Gms.Common;
using Firebase.Messaging;
namespace miemss_xamarin.Droid
{
[Activity(Label = "miemss_xamarin", Icon = "#mipmap/icon", Theme = "#style/MainTheme", ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
TextView msgText;
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
I've tried several solutions that I found on how to use ViewRenderer to show android activities on Xamarain.forms but still couldn't have it worked perfectly. I want to show the activity NewViewRenderer in Xamarin Forms? Right Now when I click on Regions Icon, it shown an empty page with back button to the main page!
When you set the type of NewViewRenderer, you make a mistake. You should set ViewRenderer<NewView, Android.Views.View>
[assembly: ExportRenderer(typeof(NewView), typeof(NewViewRenderer))]
namespace CustomRenderDemo.Droid
{
public class NewViewRenderer : ViewRenderer<NewView, Android.Views.View>
{
NewViewRenderer newViewRenderer;
Android.Widget.Switch btnRegion1; Android.Widget.Switch btnRegion2; Android.Widget.Switch btnRegion3; Android.Widget.Switch btnRegion4; Android.Widget.Switch btnRegion5;
Context context;
public NewViewRenderer(Context context) : base(context)
{
this.context = context;
}
protected override void OnElementChanged(ElementChangedEventArgs<NewView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
// var context = new NewViewRenderer(Forms.Context);
//SetNativeControl(context);
var context = Android.App.Application.Context;
var view = LayoutInflater.From(context).Inflate(Resource.Layout.NotificationLayout, null, false);
// LayoutInflater minflater = context.GetSystemService(Context.LayoutInflaterService) as LayoutInflater;
// var view = minflater.Inflate(Resource.Layout.NotificationLayout, this, false);
var msgText = view.FindViewById<TextView>(Resource.Id.msgText);
btnRegion1 = view.FindViewById<Android.Widget.Switch>(Resource.Id.SubscribeToRegion1);
btnRegion2 = view.FindViewById<Android.Widget.Switch>(Resource.Id.SubscribeToRegion2);
btnRegion3 = view.FindViewById<Android.Widget.Switch>(Resource.Id.SubscribeToRegion3);
btnRegion4 = view.FindViewById<Android.Widget.Switch>(Resource.Id.SubscribeToRegion4);
btnRegion5 = view.FindViewById<Android.Widget.Switch>(Resource.Id.SubscribeToRegion5);
SetNativeControl(view);
// AddView(view);
// new NewView(context);
// SetNativeControl(new MyView(context));
// Control.AddView(view);
// base.SetNativeControl(view);
// It always shows red underline under view, so I
}
if (e.NewElement != null)
{
btnRegion1.CheckedChange += (a, b) =>
{
bool isChecked = b.IsChecked;
//if (isChecked)
// FirebaseMessaging.Instance.SubscribeToTopic("R1");
//else
// FirebaseMessaging.Instance.UnsubscribeFromTopic("R1");
};
btnRegion2.CheckedChange += (c, d) =>
{
bool isChecked = d.IsChecked;
//if (isChecked)
// FirebaseMessaging.Instance.SubscribeToTopic("R2");
//else
// FirebaseMessaging.Instance.UnsubscribeFromTopic("R2");
};
btnRegion3.CheckedChange += (e, f) =>
{
bool isChecked = f.IsChecked;
//if (isChecked)
// FirebaseMessaging.Instance.SubscribeToTopic("R3");
//else
// FirebaseMessaging.Instance.UnsubscribeFromTopic("R3");
};
btnRegion4.CheckedChange += (g, h) =>
{
bool isChecked = h.IsChecked;
//if (isChecked)
// FirebaseMessaging.Instance.SubscribeToTopic("R4");
//else
// FirebaseMessaging.Instance.UnsubscribeFromTopic("R4");
};
btnRegion5.CheckedChange += (i, j) =>
{
bool isChecked = j.IsChecked;
//if (isChecked)
// FirebaseMessaging.Instance.SubscribeToTopic("R5");
//else
// FirebaseMessaging.Instance.UnsubscribeFromTopic("R5");
};
}
}
}
Here is running sceenshot.
The issue is the base type you are using for your NewViewRenderer:
public class NewViewRenderer : ViewRenderer<miemss_xamarin.NewView,miemss_xamarin.Droid.NewViewRenderer>
You want your native control to be a Android.Views.View, not your NewViewrenderer. So try this instead:
public class NewViewRenderer : Xamarin.Forms.Platform.Android.ViewRenderer<NewView, Android.Views.View>
or if you need Android.AppCompat views:
public class NewViewRenderer : Xamarin.Forms.Platform.Android.AppCompat.ViewRenderer<NewView, Android.Views.View>
I have an already build Xamarin App but now I want to add the Sign Up / Login Page at the Start. When I open the App, first It open a Sign up Page.
I add a Blank Page with Title "Welcome to App" and Add a Button, but the Button doesn't work and only It works when it uses the Navigation of Other Pages, why? and how to add a sign up form on blank page?
IMAGE: It now looks like this.
I want to remove these Credentials, Accounts e.t.c from the top and just have an blank page of Sign Up.
Here is the Code, I hope it helps you to understand it better. If you need anything else, kindly ask for it.
Thanks :)
UPDATE: #Jason Comment : I removed Login Code from MainPage.xml, now the Navigation Tabs are no longer there but now the Button isn't working (when I click on it, nothing happens).
LoginPage.xml
<?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:converters="clr-namespace:Osma.Mobile.App.Converters;assembly=Osma.Mobile.App"
xmlns:behaviours="clr-namespace:Osma.Mobile.App.Behaviors;assembly=Osma.Mobile.App"
xmlns:components="clr-namespace:Osma.Mobile.App.Views.Components;assembly=Osma.Mobile.App"
x:Class="Osma.Mobile.App.Views.Login.LoginPage"
Title="Login"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
ios:Page.LargeTitleDisplay="Always"
>
<ContentPage.Content>
<StackLayout>
<Label Text="Welcome to App"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
<Button Text="Enter"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"
Command="{Binding ButtonClickedCommand}"
/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
LoginPage.xml.cs
using System;
using System.Collections.Generic;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Osma.Mobile.App.Views.Login
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class LoginPage : ContentPage
{
public LoginPage()
{
InitializeComponent();
}
}
}
LoginViewMode.cs
using System;
using System.Reactive.Linq;
using System.Collections.Generic;
using System.Text;
using System.Windows.Input;
using System.Threading.Tasks;
using Acr.UserDialogs;
using Hyperledger.Aries.Contracts;
using Hyperledger.Aries.Features.DidExchange;
using Hyperledger.Aries.Utils;
using Osma.Mobile.App.Events;
using Osma.Mobile.App.Extensions;
using Osma.Mobile.App.Services;
using Osma.Mobile.App.Services.Interfaces;
using ReactiveUI;
using Xamarin.Forms;
using Xamarin.Essentials;
using Osma.Mobile.App.ViewModels.Credentials;
namespace Osma.Mobile.App.ViewModels.Login
{
public class LoginViewModel : ABaseViewModel
{
private readonly ICustomAgentContextProvider _agentContextProvider;
private readonly IConnectionService _connectionService;
public LoginViewModel(
IUserDialogs userDialogs,
INavigationService navigationService,
ICustomAgentContextProvider agentContextProvider,
IConnectionService defaultConnectionService) :
base("Login", userDialogs, navigationService)
{
_agentContextProvider = agentContextProvider;
_connectionService = defaultConnectionService;
}
public ICommand ButtonClickedCommand => new Command(async () => await NavigationService.NavigateToAsync<CredentialsViewModel>());
}
}
App.xaml.css
using System.Threading.Tasks;
using Autofac;
using Microsoft.AppCenter;
using Microsoft.AppCenter.Analytics;
using Microsoft.AppCenter.Crashes;
using Osma.Mobile.App.Services.Interfaces;
using Osma.Mobile.App.Utilities;
using Osma.Mobile.App.ViewModels;
using Osma.Mobile.App.ViewModels.Login;
using Osma.Mobile.App.ViewModels.Account;
using Osma.Mobile.App.ViewModels.Connections;
using Osma.Mobile.App.ViewModels.CreateInvitation;
using Osma.Mobile.App.ViewModels.Credentials;
using Osma.Mobile.App.Views;
using Osma.Mobile.App.Views.Login;
using Osma.Mobile.App.Views.Account;
using Osma.Mobile.App.Views.Connections;
using Osma.Mobile.App.Views.CreateInvitation;
using Osma.Mobile.App.Views.Credentials;
using Xamarin.Forms;
using Xamarin.Forms.Internals;
using Xamarin.Forms.Xaml;
using LoginPage = Osma.Mobile.App.Views.Login.LoginPage;
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace Osma.Mobile.App
{
public partial class App : Application
{
public new static App Current => Application.Current as App;
public Palette Colors;
private readonly INavigationService _navigationService;
private readonly ICustomAgentContextProvider _contextProvider;
public App(IContainer container)
{
InitializeComponent();
MainPage = new LoginPage();
Colors.Init();
_navigationService = container.Resolve<INavigationService>();
_contextProvider = container.Resolve<ICustomAgentContextProvider>();
InitializeTask = Initialize();
}
Task InitializeTask;
private async Task Initialize()
{
//Pages
_navigationService.AddPageViewModelBinding<MainViewModel, MainPage>();
_navigationService.AddPageViewModelBinding<LoginViewModel, LoginPage>();
_navigationService.AddPageViewModelBinding<ConnectionsViewModel, ConnectionsPage>();
_navigationService.AddPageViewModelBinding<ConnectionViewModel, ConnectionPage>();
_navigationService.AddPageViewModelBinding<RegisterViewModel, RegisterPage>();
_navigationService.AddPageViewModelBinding<AcceptInviteViewModel, AcceptInvitePage>();
_navigationService.AddPageViewModelBinding<CredentialsViewModel, CredentialsPage>();
_navigationService.AddPageViewModelBinding<CredentialViewModel, CredentialPage>();
_navigationService.AddPageViewModelBinding<AccountViewModel, AccountPage>();
_navigationService.AddPageViewModelBinding<CreateInvitationViewModel, CreateInvitationPage>();
if (_contextProvider.AgentExists())
{
await _navigationService.NavigateToAsync<LoginViewModel>();
}
else
{
await _navigationService.NavigateToAsync<LoginViewModel>();
}
}
protected override void OnStart()
{
#if !DEBUG
AppCenter.Start("ios=" + AppConstant.IosAnalyticsKey + ";" +
"android=" + AppConstant.AndroidAnalyticsKey + ";",
typeof(Analytics), typeof(Crashes));
#endif
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
}
MainPage.xml
<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:connections="clr-namespace:Osma.Mobile.App.Views.Connections;assembly=Osma.Mobile.App"
xmlns:credentials="clr-namespace:Osma.Mobile.App.Views.Credentials;assembly=Osma.Mobile.App"
xmlns:account="clr-namespace:Osma.Mobile.App.Views.Account;assembly=Osma.Mobile.App"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
x:Class="Osma.Mobile.App.Views.MainPage"
CurrentPageChanged="CurrentPageChanged"
Appearing="Appearing"
>
<connections:ConnectionsPage
Icon="connection_icon.png"
ios:NavigationPage.PrefersLargeTitles="true"
BindingContext="{Binding Connections}">
</connections:ConnectionsPage>
<credentials:CredentialsPage
Icon="credentials_icon.png"
ios:NavigationPage.PrefersLargeTitles="true"
BindingContext="{Binding Credentials}">
</credentials:CredentialsPage>
<account:AccountPage
Icon="account_icon.png"
ios:NavigationPage.PrefersLargeTitles="true"
BindingContext="{Binding Account}">
</account:AccountPage>
</TabbedPage>
MainViewModel.cs
using System.Threading.Tasks;
using Acr.UserDialogs;
using Osma.Mobile.App.Services.Interfaces;
using Osma.Mobile.App.ViewModels.Login;
using Osma.Mobile.App.ViewModels.Account;
using Osma.Mobile.App.ViewModels.Connections;
using Osma.Mobile.App.ViewModels.CreateInvitation;
using Osma.Mobile.App.ViewModels.Credentials;
using ReactiveUI;
namespace Osma.Mobile.App.ViewModels
{
public class MainViewModel : ABaseViewModel
{
public MainViewModel(
IUserDialogs userDialogs,
INavigationService navigationService,
LoginViewModel loginViewModel,
ConnectionsViewModel connectionsViewModel,
CredentialsViewModel credentialsViewModel,
AccountViewModel accountViewModel,
CreateInvitationViewModel createInvitationViewModel)
: base(
nameof(MainViewModel),
userDialogs,
navigationService
)
{
Login = loginViewModel;
Connections = connectionsViewModel;
Credentials = credentialsViewModel;
Account = accountViewModel;
CreateInvitation = createInvitationViewModel;
}
public override async Task InitializeAsync(object navigationData)
{
await Login.InitializeAsync(null);
await Connections.InitializeAsync(null);
await Credentials.InitializeAsync(null);
await Account.InitializeAsync(null);
await CreateInvitation.InitializeAsync(null);
await base.InitializeAsync(navigationData);
}
#region Bindable Properties
private LoginViewModel _login;
public LoginViewModel Login
{
get => _login;
set => this.RaiseAndSetIfChanged(ref _login, value);
}
private ConnectionsViewModel _connections;
public ConnectionsViewModel Connections
{
get => _connections;
set => this.RaiseAndSetIfChanged(ref _connections, value);
}
private CredentialsViewModel _credentials;
public CredentialsViewModel Credentials
{
get => _credentials;
set => this.RaiseAndSetIfChanged(ref _credentials, value);
}
private AccountViewModel _account;
public AccountViewModel Account
{
get => _account;
set => this.RaiseAndSetIfChanged(ref _account, value);
}
private CreateInvitationViewModel _createInvitation;
public CreateInvitationViewModel CreateInvitation
{
get => _createInvitation;
set => this.RaiseAndSetIfChanged(ref _createInvitation, value);
}
#endregion
}
}
I do not see that you have a NavigationPage instance anywhere, so how does your NavigationService works?
NavigationService usually inserts a page to a stack of pages on a NaviagtionPage instance.
I see in App.xaml.cs you make the LoginPage your main page, but where do you switch it to a NavigationPage, or to your TabbedPage?
You need to check what your MainPage should really be.
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.