double Percentage = 89.5234234234;
Output : 89.52%
Code Behind You Can Try this.
Percentage.ToString("0.00");
A blog about Xamarin.Forms, .NET MAUI, .NET MAUI Handler, Xamarin.iOS, Xamarin.Android, Custom Renderer, Xamarin Custom Control, Push Notification, Play Video From URI, Data Bindings. Xamarin Calendar
double Percentage = 89.5234234234;
Output : 89.52%
Code Behind You Can Try this.
Percentage.ToString("0.00");
<?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:views="clr-namespace:HorizontalCalendar.Views;assembly=HorizontalCalendar"
x:Class="TestApp.MainPage">
<StackLayout >
<views:HorizontalCalendarControl x:Name="calendarControl"/>
</StackLayout>
</ContentPage>
UI Customization<Label Text="{Binding Source={x:Reference calendarControl},Path=SelectedDate}" /> <views:HorizontalCalendarControl x:Name="calendarControl"/>
<views:HorizontalCalendarControl SelectedDateCommand="{Binding SelectedDateCommand}" x:Name="calendarControl" />
private DateTime _selectedDate;
public DateTime SelectedDate
{
get => _selectedDate;
set => SetProperty(ref _selectedDate, value);
}
public ICommand SelectedDateCommand => new Command<DateTime>((selectedDate) =>
{
SelectedDate = selectedDate;
});
Example :
Navigation to Other Page.
Navigating to another Page From App.xaml.cs (Start Up)
var navigationService = DependencyService.Resolve<INavigationService>();
navigationService.NavigateToAsync<LoginViewModel>(isRootPage: true);
Navigating to another Page From ViewModel
NavigationService.NavigateToAsync<LoginViewModel>(isRootPage: true);
Navigating to another Page With Parameter
var obj = new { firstName="Hello", age = 26 }
NavigationService.NavigateToAsync<LoginViewModel>(obj,isRootPage: false);
Accessing Passed Parameter
All ViewModels are inherited BaseViewModel and it contains Initialize method that you just need to override in All ViewModels.
protected internal override void Initialize(object navigationData, Page uiRef = null) { base.Initialize(navigationData); string firstName = TryGetValue(navigationData,nameof(firstName)); int age = TryGetValue<int>(navigationData,nameof(age)); }
Naming Convention of Page & ViewModel
Now Create INavigationService Interface that Includes the following methods.
INavigationService.cs
public interface INavigationService
{
T GetPageViewModel<T>() where T : new();
//T GetPageView<T>() where T : Page, new();
Task RemovePages<T>() where T : new();
Task NavigateToAsync<TViewModel>(object parameter = null, bool isRootPage = false, bool isPopupPage = false, bool isSubscribeOnAppear = false, bool isFetchUI = false) where TViewModel : BaseViewModel;
void InsertPageBeforeLastPage<TViewModel>(object parameter = null, bool isSubscribeOnAppear = false, bool isFetchUI = false) where TViewModel : BaseViewModel;
}
Usage:
Task RemovePages<T>() where T : new();
This method will removed all pages till it reach the specified ViewModel Name.
Task NavigateToAsync<TViewModel>(object parameter = null, bool isRootPage = false, bool isSubscribeOnAppear = false, bool isFetchUI = false) where TViewModel : BaseViewModel;
This method used for navigating from one page to another page.
parameter: It will accept any type of object that you want to bring to another page.
isRootPage: It will set the page as a root page, like App.Current.MainPage = new NavigationPage(Page Name)
isSubscribeOnAppear: This Will Subscribe OnAppear() Method of page.
isFetchUI: This flag used for getting view reference in ViewModel.
TViewModel: BaseViewModel: Create BaseViewModel Class that contains Some Common Property and INavigationService Declaration.
BaseViewModel.cs
public class BaseViewModel : INotifyPropertyChanged
{
#region Properties
private string _title;
public string Title
{
get => _title;
set => SetProperty(ref _title, value);
}
private bool _isBusy;
public bool IsBusy
{
get => _isBusy;
set => SetProperty(ref _isBusy, value);
}
private bool _isRefreshing;
public bool IsRefreshing
{
get => _isRefreshing;
set => SetProperty(ref _isRefreshing, value);
}
public bool IsRefreshData { get; set; }
#endregion
#region Services
protected readonly INavigationService NavigationService;
#endregion
#region Commands
public ICommand ItemSelectedCommand { get; protected set; }
public ICommand RefreshCommand { get; protected set; }
#endregion
#region Construtor
public BaseViewModel()
{
NavigationService = DependencyService.Resolve<INavigationService>();
}
#endregion
#region Methods
protected internal virtual void Initialize(object navigationData, Page uiRef = null) { }
protected internal virtual void OnAppearing() { }
public static T TryGetValue<T>(object navigationData, string propertyName = "") where T : new()
{
var returnValue = new T();
try
{
if (navigationData != null)
{
if (string.IsNullOrWhiteSpace(propertyName))
{
returnValue = (T)navigationData;
}
else
{
returnValue = (T)navigationData.GetType().GetProperty(propertyName).GetValue(navigationData);
}
}
}
catch (Exception ex)
{
}
return returnValue;
}
public static string TryGetValue(object navigationData, string propertyName = "")
{
var returnValue = string.Empty;
try
{
if (navigationData != null)
{
if (string.IsNullOrWhiteSpace(propertyName))
{
returnValue = (string)navigationData;
}
else
{
returnValue = (string)navigationData.GetType().GetProperty(propertyName).GetValue(navigationData);
}
}
}
catch (Exception ex)
{
}
return returnValue;
}
#endregion
protected bool SetProperty<T>(ref T backingStore, T value,
[CallerMemberName] string propertyName = "",
Action onChanged = null)
{
if (EqualityComparer<T>.Default.Equals(backingStore, value))
return false;
backingStore = value;
onChanged?.Invoke();
OnPropertyChanged(propertyName);
return true;
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var changed = PropertyChanged;
if (changed == null)
return;
changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
Create NavigationService class that Implement INavigationService.cs Interface.
NavigationService.cs
public class NavigationService : INavigationService
{
public async Task NavigateToAsync<TViewModel>(object parameter = null, bool isRootPage = false, bool isPopupPage = false, bool isSubscribeOnAppear = false, bool isFetchUI = false) where TViewModel : BaseViewModel
{
Type viewModelType = typeof(TViewModel);
Type pageType = GetPageTypeForViewModel(viewModelType);
if (pageType == null)
throw new Exception($"Cannot locate page type for {viewModelType}");
try
{
BaseViewModel viewModel = Activator.CreateInstance(viewModelType) as BaseViewModel;
ContentPage page = Activator.CreateInstance(pageType) as ContentPage;
page.BindingContext = viewModel;
if (isRootPage)
Application.Current.MainPage = new NavigationPage(page);
else
{
var navigationPage = Application.Current.MainPage as NavigationPage;
if (navigationPage != null)
await navigationPage.PushAsync(page, true);
else
Application.Current.MainPage = new NavigationPage(page);
}
if (!isFetchUI)
viewModel.Initialize(parameter);
else
viewModel.Initialize(parameter, page);
if (isSubscribeOnAppear)
{
page.Appearing -= new EventHandler(OnAppearing);
page.Appearing += new EventHandler(OnAppearing);
}
}
catch (Exception ex)
{
}
}
private void OnAppearing(object sender, EventArgs e)
{
var viewModel = ((Page)(sender)).BindingContext as BaseViewModel;
if (viewModel.IsRefreshData) viewModel.OnAppearing();
}
private Type GetPageTypeForViewModel(Type viewModelType)
{
var viewModelAssemblyName = viewModelType.GetTypeInfo().Assembly.FullName;
var viewName = viewModelType.FullName.Replace("ViewModel", "View");
var viewAssemblyName = string.Format(
CultureInfo.InvariantCulture, "{0}, {1}", viewName, viewModelAssemblyName);
var viewType = Type.GetType(viewAssemblyName);
return viewType;
}
public T GetPageViewModel<T>() where T : new()
{
var mainPage = Application.Current.MainPage as NavigationPage;
var pageNeedToReturn = mainPage.Navigation.NavigationStack.Where(f => f.BindingContext.GetType() == typeof(T)).FirstOrDefault();
if (pageNeedToReturn != null)
{
return (T)pageNeedToReturn.BindingContext;
}
return default(T);
}
//public T GetPageView<T>() where T : Page, new()
//{
// var mainPage = Application.Current.MainPage as NavigationPage;
// var pageNeedToReturn = mainPage.Navigation.NavigationStack.Where(f => f.GetType() == typeof(T)).FirstOrDefault();
// if (pageNeedToReturn != null)
// {
// return (T)pageNeedToReturn;
// }
// return default(T);
//}
public void InsertPageBeforeLastPage<TViewModel>(object parameter = null, bool isSubscribeOnAppear = false, bool isFetchUI = false) where TViewModel : BaseViewModel
{
Type viewModelType = typeof(TViewModel);
Type pageType = GetPageTypeForViewModel(viewModelType);
if (pageType == null)
throw new Exception($"Cannot locate page type for {viewModelType}");
try
{
BaseViewModel viewModel = Activator.CreateInstance(viewModelType) as BaseViewModel;
Page page = Activator.CreateInstance(pageType) as Page;
page.BindingContext = viewModel;
var lastPage = App.Current.MainPage.Navigation.NavigationStack.LastOrDefault();
if (!isFetchUI)
viewModel.Initialize(parameter);
else
viewModel.Initialize(parameter, page);
if (isSubscribeOnAppear)
{
page.Appearing -= new EventHandler(OnAppearing);
page.Appearing += new EventHandler(OnAppearing);
}
App.Current.MainPage.Navigation.InsertPageBefore(page, lastPage);
}
catch (Exception ex)
{
}
}
/// <summary>
/// Specified the page name (it will remove pages till specified page name)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public async Task RemovePages<T>() where T : new()
{
var returnValue = new T();
var pages = App.Current.MainPage.Navigation.NavigationStack.ToList();
for (int maxPageIndex = pages.Count - 1; maxPageIndex >= 0; maxPageIndex--)
{
var currnetPage = pages[maxPageIndex];
if (currnetPage != null)
{
if (currnetPage.BindingContext.GetType() == returnValue.GetType())
{
break;
}
else
{
App.Current.MainPage.Navigation.RemovePage(currnetPage);
}
}
}
await App.Current.MainPage.Navigation.PopAsync();
}
Registration of NavigationService on App.xaml.cs