I created a custom DatePicker to look like it has placeholder, but the
problem is, when clicking the DatePicker then when the DatePicker
Dialog opens and I click on okay with the preselected/default date
value of today, The date is not written in the field. Below is my
code.
I think the reason is that since "Date" property has a default value
of today and there is no change in the selection when the "OK" button
was clicked
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace XXX.XXX.Mobile.Controls
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class DatePickerWithPlaceHolder : DatePicker
{
public static readonly BindableProperty NullableDateProperty = BindableProperty.Create(nameof(NullableDate),typeof(DateTime?),typeof(DatePickerWithPlaceHolder), null, BindingMode.TwoWay);
private string _format;
public DateTime? NullableDate
{
get => (DateTime?)GetValue(NullableDateProperty);
set
{
SetValue(NullableDateProperty, value);
UpdateDate();
}
}
private void UpdateDate()
{
DatePickerWithPlaceHolder datePicker = this;
if (NullableDate.HasValue)
{
if (null != _format) Format = _format;
Date = NullableDate.Value;
datePicker.FontAttributes = FontAttributes.None;
datePicker.TextColor = Color.Black;
}
else
{
_format = Format;
Format = "Select Date";
datePicker.FontAttributes = FontAttributes.Italic;
datePicker.TextColor = Color.Gray;
}
}
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
UpdateDate();
}
protected override void OnPropertyChanged(string propertyName = null)
{
base.OnPropertyChanged(propertyName);
if (propertyName == "Date") NullableDate = Date;
if (propertyName == "NullableDate") UpdateDate();
}
}
}
I think you need set NullableDate to null in the background code.
Below is the sample code for your reference:
DatePickerWithPlaceHolder.cs
public class DatePickerWithPlaceHolder : DatePicker
{
private string _format = null;
public static readonly BindableProperty NullableDateProperty = BindableProperty.Create<DatePickerWithPlaceHolder, DateTime?>(p => p.NullableDate, null, BindingMode.TwoWay);
public DateTime? NullableDate
{
get { return (DateTime?)GetValue(NullableDateProperty); }
set { SetValue(NullableDateProperty, value); UpdateDate(); }
}
private void UpdateDate()
{
if (NullableDate.HasValue) { if (null != _format) Format = _format; Date = NullableDate.Value; }
else { _format = Format; Format = "Select Date ..."; FontAttributes = FontAttributes.Italic;
TextColor = Color.Green;
}
}
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
UpdateDate();
}
protected override void OnPropertyChanged(string propertyName = null)
{
base.OnPropertyChanged(propertyName);
if (propertyName == "Date") NullableDate = Date;
}
}
Consume it in Xaml:
<appentrymask:DatePickerWithPlaceHolder x:Name="myDatePicker"/>
Initialize the NullableDate in code behind:
public MainPage()
{
InitializeComponent();
myDatePicker.NullableDate = null;
}
Last but not least,for detecting the OK or Cancel event, you could refer to this thread.
Related
I am having a requirement like a Month picker which is showing only month and year and not the date .How can we achieve the same for both IOS and Android platform using Xamarin forms ?
You could implement it by using Custom Renderer
in Forms
create a custom View
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;
namespace App20
{
public class MonthYearPickerView :View
{
public static readonly BindableProperty FontSizeProperty = BindableProperty.Create(
propertyName: nameof(FontSize),
returnType: typeof(double),
declaringType: typeof(MonthYearPickerView),
defaultValue: (double)24,
defaultBindingMode: BindingMode.TwoWay);
[TypeConverter(typeof(FontSizeConverter))]
public double FontSize
{
get => (double)GetValue(FontSizeProperty);
set => SetValue(FontSizeProperty, value);
}
public static readonly BindableProperty TextColorProperty = BindableProperty.Create(
propertyName: nameof(TextColor),
returnType: typeof(Color),
declaringType: typeof(MonthYearPickerView),
defaultValue: Color.White,
defaultBindingMode: BindingMode.TwoWay);
public Color TextColor
{
get => (Color)GetValue(TextColorProperty);
set => SetValue(TextColorProperty, value);
}
public static readonly BindableProperty InfiniteScrollProperty = BindableProperty.Create(
propertyName: nameof(InfiniteScroll),
returnType: typeof(bool),
declaringType: typeof(MonthYearPickerView),
defaultValue: true,
defaultBindingMode: BindingMode.TwoWay);
public bool InfiniteScroll
{
get => (bool)GetValue(InfiniteScrollProperty);
set => SetValue(InfiniteScrollProperty, value);
}
public static readonly BindableProperty DateProperty = BindableProperty.Create(
propertyName: nameof(Date),
returnType: typeof(DateTime),
declaringType: typeof(MonthYearPickerView),
defaultValue: default,
defaultBindingMode: BindingMode.TwoWay);
public DateTime Date
{
get => (DateTime)GetValue(DateProperty);
set => SetValue(DateProperty, value);
}
public static readonly BindableProperty MaxDateProperty = BindableProperty.Create(
propertyName: nameof(MaxDate),
returnType: typeof(DateTime?),
declaringType: typeof(MonthYearPickerView),
defaultValue: default,
defaultBindingMode: BindingMode.TwoWay);
public DateTime? MaxDate
{
get => (DateTime?)GetValue(MaxDateProperty);
set => SetValue(MaxDateProperty, value);
}
public static readonly BindableProperty MinDateProperty = BindableProperty.Create(
propertyName: nameof(MinDate),
returnType: typeof(DateTime?),
declaringType: typeof(MonthYearPickerView),
defaultValue: default,
defaultBindingMode: BindingMode.TwoWay);
public DateTime? MinDate
{
get => (DateTime?)GetValue(MinDateProperty);
set => SetValue(MinDateProperty, value);
}
}
}
in iOS
using System;
using App20;
using App20.iOS;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(MonthYearPickerView), typeof(MonthYearPickerRenderer))]
namespace App20.iOS
{
public class MonthYearPickerRenderer : ViewRenderer<MonthYearPickerView, UITextField>
{
private DateTime _selectedDate;
private UITextField _dateLabel;
private PickerDateModel _pickerModel;
protected override void OnElementChanged(ElementChangedEventArgs<MonthYearPickerView> e)
{
base.OnElementChanged(e);
_dateLabel = new UITextField();
_dateLabel.TextAlignment = UITextAlignment.Center;
var dateToday = DateTime.Today;
SetupPicker(new DateTime(dateToday.Year, dateToday.Month, 1));
SetNativeControl(_dateLabel);
Control.EditingChanged += ControlOnEditingChanged;
Element.PropertyChanged += Element_PropertyChanged;
}
private void ControlOnEditingChanged(object sender, EventArgs e)
{
var currentDate = $"{Element.Date.Month:D2} | {Element.Date.Year}";
if (_dateLabel.Text != currentDate)
{
_dateLabel.Text = currentDate;
}
}
protected override void Dispose(bool disposing)
{
Element.PropertyChanged -= Element_PropertyChanged;
base.Dispose(disposing);
}
private void SetupPicker(DateTime date)
{
var datePicker = new UIPickerView();
_pickerModel = new PickerDateModel(datePicker, date, Element.MaxDate, Element.MinDate);
datePicker.ShowSelectionIndicator = true;
_selectedDate = date;
_pickerModel.PickerChanged += (sender, e) =>
{
_selectedDate = e;
};
datePicker.Model = _pickerModel;
_pickerModel.MaxDate = Element.MaxDate ?? DateTime.MaxValue;
_pickerModel.MinDate = Element.MinDate ?? DateTime.MinValue;
var toolbar = new UIToolbar
{
BarStyle = UIBarStyle.Default,
Translucent = true
};
toolbar.SizeToFit();
var doneButton = new UIBarButtonItem("Done", UIBarButtonItemStyle.Done,
(s, e) =>
{
Element.Date = _selectedDate;
_dateLabel.Text = $"{Element.Date.Month:D2} | {Element.Date.Year}";
_dateLabel.ResignFirstResponder();
});
toolbar.SetItems(new[] { new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace), doneButton }, true);
_dateLabel.InputView = datePicker;
_dateLabel.Text = $"{Element.Date.Month:D2} | {Element.Date.Year}";
_dateLabel.InputAccessoryView = toolbar;
_dateLabel.TextColor = Element.TextColor.ToUIColor();
}
private void Element_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == MonthYearPickerView.MaxDateProperty.PropertyName)
{
_pickerModel.MaxDate = Element.MaxDate ?? DateTime.MinValue;
}
else if (e.PropertyName == MonthYearPickerView.MinDateProperty.PropertyName)
{
_pickerModel.MinDate = Element.MinDate ?? DateTime.MaxValue;
}
}
}
}
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using UIKit;
namespace App20.iOS
{
public class PickerDateModel : UIPickerViewModel
{
public event EventHandler<DateTime> PickerChanged;
#region Fields
private readonly List<string> _mainNamesOfMonthSource;
private readonly List<int> _mainYearsSource;
private readonly UIPickerView _picker;
private readonly int _numberOfComponents;
private readonly int _minYear;
private readonly int _maxYear;
private List<int> _years;
private List<string> _namesOfMonth;
private DateTime _selectedDate;
private DateTime _maxDate;
private DateTime _minDate;
#endregion Fields
#region Constructors
public PickerDateModel(UIPickerView datePicker, DateTime selectedDate, DateTime? maxDate, DateTime? minDate)
{
_mainNamesOfMonthSource = DateTimeFormatInfo.CurrentInfo?.MonthNames
.Where(x => !string.IsNullOrWhiteSpace(x))
.ToList();
_maxDate = maxDate ?? DateTime.MaxValue;
_minDate = minDate ?? DateTime.MinValue;
_maxYear = _maxDate.Year;
_minYear = _minDate.Year;
_years = new List<int>();
_picker = datePicker;
_namesOfMonth = _mainNamesOfMonthSource;
_numberOfComponents = 2;
SelectedDate = selectedDate;
}
#endregion Constructors
#region Properties
public DateTime SelectedDate
{
get => _selectedDate;
set
{
_selectedDate = value;
ReloadSections();
PickerChanged?.Invoke(this, value);
}
}
public DateTime MaxDate
{
get => _maxDate;
set
{
_maxDate = value;
ReloadSections();
}
}
public DateTime MinDate
{
get => _minDate;
set
{
_minDate = value;
ReloadSections();
}
}
#endregion Properties
#region Private Methods
private void ReloadSections()
{
var selectedDate = SelectedDate == DateTime.MinValue
? DateTime.Today
: SelectedDate;
_years.Clear();
for (int i = _minYear; i <= _maxYear; i++)
{
_years.Add(i);
}
_namesOfMonth = _mainNamesOfMonthSource;
if (SelectedDate.Year == MinDate.Year)
{
_namesOfMonth = _mainNamesOfMonthSource.Skip(MinDate.Month - 1).ToList();
}
if (SelectedDate.Year == MaxDate.Year)
{
_namesOfMonth = _mainNamesOfMonthSource.Take(MaxDate.Month).ToList();
}
SetCarousels(selectedDate);
}
#endregion Private Methods
#region Public Methods
public void SetCarousels(DateTime dateTime)
{
if (_picker.NumberOfComponents != _numberOfComponents) return;
var y = DateTimeFormatInfo.CurrentInfo?.GetMonthName(dateTime.Month);
var x = _namesOfMonth.IndexOf(y);
_picker.Select(x, 0, false);
_picker.Select(_years.IndexOf(dateTime.Year), 1, false);
_picker.ReloadComponent(0);
_picker.ReloadComponent(1);
}
public override nint GetComponentCount(UIPickerView pickerView)
{
return _numberOfComponents;
}
public override nint GetRowsInComponent(UIPickerView pickerView, nint component)
{
if (component == 0)
{
return _namesOfMonth.Count;
}
else if (component == 1)
{
return _years.Count;
}
else
{
return 0;
}
}
public override string GetTitle(UIPickerView pickerView, nint row, nint component)
{
if (component == 0)
{
return _namesOfMonth.Count==0 ? _namesOfMonth.First() : _namesOfMonth[(int)row];
}
else if (component == 1)
{
var list = _years;
return _years.Count==0? _years.First().ToString() : _years[(int)row].ToString();
}
else
{
return row.ToString();
}
}
public override void Selected(UIPickerView pickerView, nint row, nint component)
{
var month = GetMonthNumberByName(_namesOfMonth[(int)pickerView.SelectedRowInComponent(0)]);
var year = _years[(int)pickerView.SelectedRowInComponent(1)];
if (year == MinDate.Year)
{
month = month >= MinDate.Month ? month : MinDate.Month;
}
if (year == MaxDate.Year)
{
month = month <= MaxDate.Month ? month : MaxDate.Month;
}
SelectedDate = new DateTime(year, month, 1);
ReloadSections();
pickerView.ReloadAllComponents();
int GetMonthNumberByName(string monthName) =>
DateTime.ParseExact(monthName, "MMMM", CultureInfo.CurrentCulture).Month;
}
#endregion Public Methods
}
}
in Android
in MainActivity
public static MainActivity Instance { get; private set; }
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
Instance = this;
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
using Android.Content;
using Android.Support.V7.App;
using Android.Widget;
using App20;
using App20.Droid;
using System;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(MonthYearPickerView), typeof(MonthYearPickerRenderer))]
namespace App20.Droid
{
public class MonthYearPickerRenderer : ViewRenderer<MonthYearPickerView, EditText>
{
private readonly Context _context;
private MonthYearPickerDialog _monthYearPickerDialog;
public MonthYearPickerRenderer(Context context) : base(context)
{
_context = context;
}
protected override void OnElementChanged(ElementChangedEventArgs<MonthYearPickerView> e)
{
base.OnElementChanged(e);
CreateAndSetNativeControl();
Control.KeyListener = null;
Element.Focused += Element_Focused;
}
protected override void Dispose(bool disposing)
{
if (Control == null) return;
Element.Focused -= Element_Focused;
if (_monthYearPickerDialog != null)
{
_monthYearPickerDialog.OnDateTimeChanged -= OnDateTimeChanged;
_monthYearPickerDialog.OnClosed -= OnClosed;
_monthYearPickerDialog.Hide();
_monthYearPickerDialog.Dispose();
_monthYearPickerDialog = null;
}
base.Dispose(disposing);
}
#region Private Methods
private void ShowDatePicker()
{
if (_monthYearPickerDialog == null)
{
_monthYearPickerDialog = new MonthYearPickerDialog();
_monthYearPickerDialog.OnDateTimeChanged += OnDateTimeChanged;
_monthYearPickerDialog.OnClosed += OnClosed;
}
_monthYearPickerDialog.Date = Element.Date;
_monthYearPickerDialog.MinDate = FormatDateToMonthYear(Element.MinDate);
_monthYearPickerDialog.MaxDate = FormatDateToMonthYear(Element.MaxDate);
_monthYearPickerDialog.InfiniteScroll = Element.InfiniteScroll;
var appcompatActivity = MainActivity.Instance;
var mFragManager = appcompatActivity?.SupportFragmentManager;
if (mFragManager != null)
{
_monthYearPickerDialog.Show(mFragManager, nameof(MonthYearPickerDialog));
}
}
private void ClearPickerFocus()
{
((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
Control.ClearFocus();
}
private DateTime? FormatDateToMonthYear(DateTime? dateTime) =>
dateTime.HasValue ? (DateTime?) new DateTime(dateTime.Value.Year, dateTime.Value.Month, 1) : null;
private void CreateAndSetNativeControl()
{
var tv = new EditText(_context);
tv.SetTextColor(Element.TextColor.ToAndroid());
tv.TextSize = (float)Element.FontSize;
tv.Text = $"{Element.Date.Month:D2} | {Element.Date.Year}";
tv.Gravity = Android.Views.GravityFlags.Center;
tv.SetBackgroundColor(Element.BackgroundColor.ToAndroid());
SetNativeControl(tv);
}
#endregion
#region Event Handlers
private void Element_Focused(object sender, FocusEventArgs e)
{
if (e.IsFocused)
{
ShowDatePicker();
}
}
private void OnClosed(object sender, DateTime e)
{
ClearPickerFocus();
}
private void OnDateTimeChanged(object sender, DateTime e)
{
Element.Date = e;
Control.Text = $"{Element.Date.Month:D2} | {Element.Date.Year}";
ClearPickerFocus();
}
#endregion
}
}
using Android.App;
using Android.OS;
using Android.Views;
using Android.Widget;
using System;
using System.Linq;
namespace App20.Droid
{
public class MonthYearPickerDialog : Android.Support.V4.App.DialogFragment
{
public event EventHandler<DateTime> OnDateTimeChanged;
public event EventHandler<DateTime> OnClosed;
#region Private Fields
private const int DefaultDay = 1;
private const int MinNumberOfMonths = 1;
private const int MaxNumberOfMonths = 12;
private const int MinNumberOfYears = 1900;
private const int MaxNumberOfYears = 2100;
private NumberPicker _monthPicker;
private NumberPicker _yearPicker;
#endregion
#region Public Properties
public DateTime? MinDate { get; set; }
public DateTime? MaxDate { get; set; }
public DateTime? Date { get; set; }
public bool InfiniteScroll { get; set; }
#endregion
public void Hide() => base.Dialog?.Hide();
public override Dialog OnCreateDialog(Bundle savedInstanceState)
{
var builder = new AlertDialog.Builder(Activity);
var inflater = Activity.LayoutInflater;
var selectedDate = GetSelectedDate();
var dialog = inflater.Inflate(Resource.Layout.date_picker_dialog, null);
_monthPicker = (NumberPicker)dialog.FindViewById(Resource.Id.picker_month);
_yearPicker = (NumberPicker)dialog.FindViewById(Resource.Id.picker_year);
InitializeMonthPicker(selectedDate.Month);
InitializeYearPicker(selectedDate.Year);
SetMaxMinDate(MaxDate, MinDate);
builder.SetView(dialog)
.SetPositiveButton("Ok", (sender, e) =>
{
selectedDate = new DateTime(_yearPicker.Value, _monthPicker.Value, DefaultDay);
OnDateTimeChanged?.Invoke(dialog, selectedDate);
})
.SetNegativeButton("Cancel", (sender, e) =>
{
Dialog.Cancel();
OnClosed?.Invoke(dialog, selectedDate);
});
return builder.Create();
}
protected override void Dispose(bool disposing)
{
if (_yearPicker != null)
{
_yearPicker.ScrollChange -= YearPicker_ScrollChange;
_yearPicker.Dispose();
_yearPicker = null;
}
_monthPicker?.Dispose();
_monthPicker = null;
base.Dispose(disposing);
}
#region Private Methods
private DateTime GetSelectedDate() => Date ?? DateTime.Now;
private void InitializeYearPicker(int year)
{
_yearPicker.MinValue = MinNumberOfYears;
_yearPicker.MaxValue = MaxNumberOfYears;
_yearPicker.Value = year;
_yearPicker.ScrollChange += YearPicker_ScrollChange;
if (!InfiniteScroll)
{
_yearPicker.WrapSelectorWheel = false;
_yearPicker.DescendantFocusability = DescendantFocusability.BlockDescendants;
}
}
private void InitializeMonthPicker(int month)
{
_monthPicker.MinValue = MinNumberOfMonths;
_monthPicker.MaxValue = MaxNumberOfMonths;
_monthPicker.SetDisplayedValues(GetMonthNames());
_monthPicker.Value = month;
if (!InfiniteScroll)
{
_monthPicker.WrapSelectorWheel = false;
_monthPicker.DescendantFocusability = DescendantFocusability.BlockDescendants;
}
}
private void YearPicker_ScrollChange(object sender, View.ScrollChangeEventArgs e)
{
SetMaxMinDate(MaxDate, MinDate);
}
private void SetMaxMinDate(DateTime? maxDate, DateTime? minDate)
{
try
{
if (maxDate.HasValue)
{
var maxYear = maxDate.Value.Year;
var maxMonth = maxDate.Value.Month;
if (_yearPicker.Value == maxYear)
{
_monthPicker.MaxValue = maxMonth;
}
else if (_monthPicker.MaxValue != MaxNumberOfMonths)
{
_monthPicker.MaxValue = MaxNumberOfMonths;
}
_yearPicker.MaxValue = maxYear;
}
if (minDate.HasValue)
{
var minYear = minDate.Value.Year;
var minMonth = minDate.Value.Month;
if (_yearPicker.Value == minYear)
{
_monthPicker.MinValue = minMonth;
}
else if (_monthPicker.MinValue != MinNumberOfMonths)
{
_monthPicker.MinValue = MinNumberOfMonths;
}
_yearPicker.MinValue = minYear;
}
_monthPicker.SetDisplayedValues(GetMonthNames(_monthPicker.MinValue));
}
catch (Exception e)
{
}
}
private string[] GetMonthNames(int start = 1) =>
System.Globalization.DateTimeFormatInfo.CurrentInfo?.MonthNames.Skip(start - 1).ToArray();
#endregion
}
}
create date_picker_dialog.xml in Resource ->layout
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal">
<NumberPicker
android:id="#+id/picker_month"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:layout_marginRight="20dp">
</NumberPicker>
<NumberPicker
android:id="#+id/picker_year"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</NumberPicker>
</LinearLayout>
</LinearLayout>
Now you can reference it in Xaml
<StackLayout VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
<local:MonthYearPickerView
Date="06.15.2020"
BackgroundColor="LightBlue"
WidthRequest="150"
MinDate="01.01.2020"
MaxDate="12.31.2050"
HorizontalOptions="CenterAndExpand"
VerticalOptions="Center" />
</StackLayout>
Ok, so I've been trying to get the custom renderer working but I have a problem.
The Xamarin Forums discussion is here: https://forums.xamarin.com/discussion/comment/376813#Comment_376813
The problem is tht when I zoom out the webview stays in a part of the screen and doesn't fit the whole screen.
I add the code of the project:
MyWebView.cs
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;
namespace CofarLE_Ejemplo_5
{
public class MyWebView : WebView
{
public int ZoomInLevel
{
get { return (int)GetValue(ZoomInLevelProperty); }
set { SetValue(ZoomInLevelProperty, value); }
}
public bool EnableZoomControl
{
get { return (bool)GetValue(EnableZoomControlProperty); }
set { SetValue(EnableZoomControlProperty, value); }
}
public static readonly BindableProperty ZoomInLevelProperty = BindableProperty.Create(propertyName: "ZoomInLevel", returnType: typeof(int), declaringType: typeof(MyWebView), defaultValue: 100, propertyChanged: OnZoomInLevelPropertyChanged);
public static readonly BindableProperty EnableZoomControlProperty = BindableProperty.Create(propertyName: "EnableZoomControl", returnType: typeof(bool), declaringType: typeof(MyWebView), defaultValue: false, propertyChanged: OnEnableZoomChanged);
private static void OnZoomInLevelPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var control1 = (MyWebView)bindable;
control1.ZoomInLevel = (int)newValue;
}
private static void OnEnableZoomChanged(BindableObject bindable, object oldValue, object newValue)
{
var control1 = (MyWebView)bindable;
control1.EnableZoomControl = (bool)newValue;
}
}
}
MyWebViewRendereriOS.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using CofarLE_Ejemplo_5;
using CofarLE_Ejemplo_5.iOS;
using Foundation;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(MyWebView), typeof(MyWebViewRendereriOS))]
namespace CofarLE_Ejemplo_5.iOS
{
public class MyDelegate : UIScrollViewDelegate
{
public UIView myView;
public UIView ViewForZoom;
public MyDelegate(UIView view)
{
myView = view;
ViewForZoom = view;
}
public override UIView ViewForZoomingInScrollView(UIScrollView scrollView)
{
MessagingCenter.Subscribe<object, bool>(this, "zoom", (sender, arg) => {
if (arg == true)
{
myView.ContentMode = UIViewContentMode.ScaleToFill;
ViewForZoom = myView;
}
else
{
ViewForZoom = null;
}
});
return ViewForZoom;
}
}
public class MyWebViewRendereriOS : WebViewRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (NativeView != null && e.NewElement != null)
{
var control1 = NativeView as UIWebView;
if (e.OldElement != null)
{
e.OldElement.PropertyChanged -= OnElementPropertyChanged;
}
if (e.NewElement != null)
{
e.NewElement.PropertyChanged += OnElementPropertyChanged;
}
control1.ScalesPageToFit = true;
control1.ScrollView.Delegate = new MyDelegate(control1);
control1.ContentMode = UIViewContentMode.ScaleToFill;
control1.ScrollView.SizeToFit();
}
}
private void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
var control1 = NativeView as UIWebView;
if (control1 == null)
{
return;
}
control1.ScalesPageToFit = true;
ScrollView.MaximumZoomScale = 2;
ScrollView.MinimumZoomScale = nfloat.Parse("0.5");
control1.ScrollView.MaximumZoomScale = 2;
control1.ScrollView.SizeToFit();
control1.ScrollView.MinimumZoomScale = nfloat.Parse("0.5");
}
}
}
you could try this,is it the effect you need(here is for Android)
1.create a custom view ZoomWebView:
public class ZoomWebView : View
{
public static readonly BindableProperty UriProperty = BindableProperty.Create(
propertyName: "Uri",
returnType: typeof(string),
declaringType: typeof(ZoomWebView),
defaultValue: default(string));
public string Uri {
get { return (string)GetValue (UriProperty); }
set { SetValue (UriProperty, value); }
}
}
2. custom renderer ZoomWebViewRenderer
public class ZoomWebViewRenderer : ViewRenderer<ZoomWebView, Android.Webkit.WebView>
{
Context _context;
public ZoomWebViewRenderer(Context context) : base(context)
{
_context = context;
}
protected override void OnElementChanged(ElementChangedEventArgs<ZoomWebView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
var webView = new Android.Webkit.WebView(_context);
webView.Settings.UseWideViewPort = true;
webView.Settings.LoadWithOverviewMode = true;
webView.Settings.SetSupportZoom(true);
webView.Settings.BuiltInZoomControls = true;
webView.Settings.DisplayZoomControls = false;
webView.SetWebViewClient(new ZoomWebViewClient());
SetNativeControl(webView);
Control.LoadUrl(Element.Uri);
}
}
class ZoomWebViewClient : WebViewClient
{
public override bool ShouldOverrideUrlLoading(WebView view, IWebResourceRequest request)
{
view.LoadUrl(request.Url.ToString());
return true;
}
}
}
3.call in the page xaml:
<ContentPage.Content>
<local:ZoomWebView Uri="https://www.microsoft.com" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
</ContentPage.Content>
I use the TimePicker and appear with a default value of "12:00 AM", I want to set the field in blank.
<TimePicker x:Name="timepicker" />
You must create your own class of TimePicker that will allow a NullableTime on XAML.
The Class should be as following:
public class MyTimePicker : TimePicker
{
private string _format = null;
public static readonly BindableProperty NullableDateProperty =
BindableProperty.Create<MyTimePicker, TimeSpan?>(p => p.NullableTime, null);
public TimeSpan? NullableTime
{
get { return (TimeSpan?)GetValue(NullableDateProperty); }
set { SetValue(NullableDateProperty, value); UpdateTime(); }
}
private void UpdateTime()
{
if (NullableTime.HasValue) { if (null != _format) Format = _format; Time = NullableTime.Value; }
else { _format = Format; Format = "pick ..."; }
}
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
UpdateTime();
}
protected override void OnPropertyChanged(string propertyName = null)
{
base.OnPropertyChanged(propertyName);
if (propertyName == "Time") NullableTime = Time;
}
}
Then on XAML you should create your control and use it as below:
<local:MyTimePicker NullableTime="{x:Null}" />
If you use this sample you will see that the default value should be pick...
I have a PIN field on a page. The PIN field is implemented with a custom class derived from stack layout, which adds item-source binding capabilities. Its item source is bound to an ObservableCollection of characters in my view-model. The issue I'm experiencing is as the title states, the pin field doesn't update upon adding, deleting from the ObservableCollection.
I've read posts with similar issues to mine. All of their solutions state to ensure that the ObservableCollection property notifies its property changed through the INotifyPropertyChanged interface call. I did this and it still isn't updating the GUI. Please help!
Here is the code:
The xaml for the PIN field
<utility:BindableStackLayout HeightRequest="40"
Orientation="Horizontal"
HorizontalOptions="Center"
ItemsSource="{Binding Pin}">
<utility:BindableStackLayout.ItemDataTemplate>
<DataTemplate>
<skia:SKCanvasView PaintSurface="OnPaintSurfacePinDigit"/>
</DataTemplate>
</utility:BindableStackLayout.ItemDataTemplate>
</utility:BindableStackLayout>
SignInPage.xaml.cs
using System;
using MNPOS.ViewModel;
using Xamarin.Forms;
using SkiaSharp.Views.Forms;
using SkiaSharp;
namespace MNPOS.View
{
public partial class SignInPage : CustomNavigationDetailPage
{
public SignInPage()
{
BindingContext = _viewModel;
InitializeComponent();
}
public void OnPaintSurfacePinDigit(object sender, SKPaintSurfaceEventArgs e)
{
...
}
private SignInViewModel _viewModel = new SignInViewModel();
}
}
SignInViewModel
using System;
using System.Text;
using System.Collections;
using MNPOS.Configuration;
using Xamarin.Forms;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace MNPOS.ViewModel
{
public class SignInViewModel : ViewModel
{
public SignInViewModel()
{
_appendDigitCommand = new Command<string>(AppendDigit);
_clearDigitCommand = new Command(ClearDigit);
_signInCommand = new Command(SignIn);
}
public void AppendDigit(string entry)
{
if (_pin.Count < Constants.MaximumPinLength)
{
_pin.Add(entry[0]);
}
}
public void ClearDigit()
{
if (_pin.Count > 0)
{
_pin.RemoveAt(Pin.Count - 1);
}
}
public void SignIn()
{
}
public Command AppendDigitCommand => _appendDigitCommand;
public Command ClearDigitCommand => _clearDigitCommand;
public Command SignInCommand => _signInCommand;
public ObservableCollection<char> Pin
{
get { return _pin; }
set
{
SetProperty<ObservableCollection<char>>(ref _pin, value, nameof(Pin));
}
}
private readonly Command _appendDigitCommand;
private readonly Command _clearDigitCommand;
private readonly Command _signInCommand;
private ObservableCollection<char> _pin = new ObservableCollection<char>();
}
}
ViewModel
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace MNPOS.ViewModel
{
public abstract class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs((propertyName)));
}
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName]string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(storage, value))
{
return false;
}
storage = value;
OnPropertyChanged(propertyName);
return true;
}
}
}
BindableStackLayout
using System.Collections;
using Xamarin.Forms;
namespace MNPOS.View.Utility
{
public class BindableStackLayout : StackLayout
{
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public static readonly BindableProperty ItemsSourceProperty =
BindableProperty.Create(nameof(ItemsSource), typeof(IEnumerable), typeof(BindableStackLayout),
propertyChanged: (bindable, oldValue, newValue) => ((BindableStackLayout)bindable).PopulateItems());
public DataTemplate ItemDataTemplate
{
get { return (DataTemplate)GetValue(ItemDataTemplateProperty); }
set { SetValue(ItemDataTemplateProperty, value); }
}
public static readonly BindableProperty ItemDataTemplateProperty =
BindableProperty.Create(nameof(ItemDataTemplate), typeof(DataTemplate), typeof(BindableStackLayout));
void PopulateItems()
{
if (ItemsSource == null) return;
foreach (var item in ItemsSource)
{
var itemTemplate = ItemDataTemplate.CreateContent() as Xamarin.Forms.View;
itemTemplate.BindingContext = item;
Children.Add(itemTemplate);
}
}
}
}
You will need to subscribe to Collection Change Events in your PropertyChanged event handler.
So in you BindableStackLayout Class change
public static readonly BindableProperty ItemsSourceProperty =
BindableProperty.Create(nameof(ItemsSource), typeof(IEnumerable), typeof(BindableStackLayout),
propertyChanged: (bindable, oldValue, newValue) => ((BindableStackLayout)bindable).PopulateItems());
to this:
public static readonly BindableProperty ItemsSourceProperty =
BindableProperty.Create(nameof(ItemsSource), typeof(IEnumerable), typeof(BindableStackLayout),
propertyChanged: (bindable, oldValue, newValue) => ((BindableStackLayout)bindable).PopulateItems(oldValue, newValue));
Then change your PopulateItems to this:
void PopulateItems(IEnumerable oldValue, IEnumerable newValue)
{
if(oldItem != null)
((ObservableCollection<char>)oldItem).CollectionChanged -= CollectionChanged;
if (newValue == null)
{
Children.Clear();
return;
}
((ObservableCollection<char>)newItem).CollectionChanged += CollectionChanged;
foreach (var item in newItem)
{
var itemTemplate = ItemDataTemplate.CreateContent() as Xamarin.Forms.View;
itemTemplate.BindingContext = item;
Children.Add(itemTemplate);
}
}
Then the CollectionChanged method would look something like this:
private void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
{
int index = e.NewStartingIndex;
foreach (var item in e.NewItems)
Children.Insert(index++, GetItemView(item));
}
break;
case NotifyCollectionChangedAction.Move:
{
var item = ObservableSource[e.OldStartingIndex];
Children.RemoveAt(e.OldStartingIndex);
Children.Insert(e.NewStartingIndex, GetItemView(item));
}
break;
case NotifyCollectionChangedAction.Remove:
{
Children.RemoveAt(e.OldStartingIndex);
}
break;
case NotifyCollectionChangedAction.Replace:
{
Children.RemoveAt(e.OldStartingIndex);
Children.Insert(e.NewStartingIndex, GetItemView(ObservableSource[e.NewStartingIndex]));
}
break;
case NotifyCollectionChangedAction.Reset:
Children.Clear();
foreach (var item in ItemsSource)
Children.Add(GetItemView(item));
break;
}
}
Please note that this was mostly typed in the browser, so there might be some typos but it should lead you in the right direction.
Good Luck
i have created one custom entry field with floating label using custom renderer like from this uri https://github.com/AlejandroRuiz/FloatingTextEntry
i need to change entry underline color as well placeholder color on button click .
Custom Entry Code :
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using Xamarin.Forms;
namespace BloodTrace.CustomControls
{
public class XfxEntry : Entry
{
public static readonly BindableProperty ErrorTextProperty = BindableProperty.Create(nameof(ErrorText),
typeof(string),
typeof(XfxEntry),
default(string), propertyChanged: OnErrorTextChangedInternal);
public static readonly BindableProperty FloatingHintEnabledProperty = BindableProperty.Create(nameof(FloatingHintEnabled),
typeof(bool),
typeof(XfxEntry),
true);
public static readonly BindableProperty ActivePlaceholderColorProperty = BindableProperty.Create(nameof(ActivePlaceholderColor),
typeof(Color),
typeof(XfxEntry),
Color.Accent);
/// <summary>
/// ActivePlaceholderColor summary. This is a bindable property.
/// </summary>
public Color ActivePlaceholderColor
{
get { return (Color)GetValue(ActivePlaceholderColorProperty); }
set { SetValue(ActivePlaceholderColorProperty, value); }
}
public Color ErrorPlaceholderColor
{
get { return (Color)GetValue(ErrorPlaceholderColorProperty); }
set { SetValue(ErrorPlaceholderColorProperty, value); }
}
public static readonly BindableProperty ErrorPlaceholderColorProperty = BindableProperty.Create(nameof(ErrorPlaceholderColor),
typeof(Color),
typeof(XfxEntry),
Color.Green);
/// <summary>
/// <c>true</c> to float the hint into a label, otherwise <c>false</c>. This is a bindable property.
/// </summary>
public bool FloatingHintEnabled
{
get { return (bool)GetValue(FloatingHintEnabledProperty); }
set { SetValue(FloatingHintEnabledProperty, value); }
}
/// <summary>
/// Gets or Sets whether or not the Error Style is 'Underline' or 'None'
/// </summary>
public ErrorDisplay ErrorDisplay { get; set; } = ErrorDisplay.None;
public bool IsErrorPlaceholderColorChange { get; set; } = false;
/// <summary>
/// Error text for the entry. An empty string removes the error. This is a bindable property.
/// </summary>
public string ErrorText
{
get { return (string)GetValue(ErrorTextProperty); }
set { SetValue(ErrorTextProperty, value); }
}
/// <summary>
/// Raised when the value of the error text changes
/// </summary>
public event EventHandler<TextChangedEventArgs> ErrorTextChanged;
private static void OnErrorTextChangedInternal(BindableObject bindable, object oldvalue, object newvalue)
{
var materialEntry = (XfxEntry)bindable;
materialEntry.OnErrorTextChanged(bindable, oldvalue, newvalue);
materialEntry.ErrorTextChanged?.Invoke(materialEntry, new TextChangedEventArgs((string)oldvalue, (string)newvalue));
}
protected virtual void OnErrorTextChanged(BindableObject bindable, object oldvalue, object newvalue) { }
}
public enum ErrorDisplay
{
Underline,
None
}
}
Android Renderer : -
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 BloodTrace;
using BloodTrace.Droid.Renderer;
using Application = Android.App.Application;
using Color = Xamarin.Forms.Color;
using AColor = Android.Graphics.Color;
using FormsAppCompat = Xamarin.Forms.Platform.Android.AppCompat;
using BloodTrace.CustomControls;
using Android.Support.Design.Widget;
using Android.Text;
using Xamarin.Forms;
using Android.Content.Res;
using Android.Views.InputMethods;
using Java.Lang;
using Android.Support.V7.Widget;
using Android.Util;
using Xamarin.Forms.Platform.Android;
using System.ComponentModel;
using Android.Text.Method;
using Android.Support.V4.View;
using BloodTrace.Droid.Extensions;
using BloodTraceSharedProject.Extensions;
[assembly: ExportRenderer(typeof(XfxEntry), typeof(XfxEntryRendererDroid))]
namespace BloodTrace.Droid.Renderer
{
public class XfxEntryRendererDroid : FormsAppCompat.ViewRenderer<XfxEntry, TextInputLayout>,
ITextWatcher,
TextView.IOnEditorActionListener
{
private bool _hasFocus;
private ColorStateList _defaultTextColor;
public XfxEntryRendererDroid(Context context) : base(context)
{
AutoPackage = false;
}
protected EditText EditText => Control.EditText;
public bool OnEditorAction(TextView v, ImeAction actionId, KeyEvent e)
{
if ((actionId == ImeAction.Done) || ((actionId == ImeAction.ImeNull) && (e.KeyCode == Keycode.Enter)))
{
Control.ClearFocus();
HideKeyboard();
((IEntryController)Element).SendCompleted();
}
return true;
}
public virtual void AfterTextChanged(IEditable s)
{
}
public virtual void BeforeTextChanged(ICharSequence s, int start, int count, int after)
{
}
public virtual void OnTextChanged(ICharSequence s, int start, int before, int count)
{
if (string.IsNullOrWhiteSpace(Element.Text) && (s.Length() == 0)) return;
((IElementController)Element).SetValueFromRenderer(Entry.TextProperty, s.ToString());
}
protected override TextInputLayout CreateNativeControl()
{
var textInputLayout = new TextInputLayout(Context);
var editText = new AppCompatEditText(Context)
{
SupportBackgroundTintList = ColorStateList.ValueOf(GetPlaceholderColor())
};
editText.SetTextSize(ComplexUnitType.Sp, (float)Element.FontSize);
textInputLayout.AddView(editText);
return textInputLayout;
}
protected override void OnElementChanged(ElementChangedEventArgs<XfxEntry> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
if (Control != null)
EditText.FocusChange -= ControlOnFocusChange;
if (e.NewElement != null)
{
var ctrl = CreateNativeControl();
SetNativeControl(ctrl);
if (!string.IsNullOrWhiteSpace(Element.AutomationId))
EditText.ContentDescription = Element.AutomationId;
_defaultTextColor = EditText.TextColors;
Focusable = true;
EditText.ShowSoftInputOnFocus = true;
// Subscribe
EditText.FocusChange += ControlOnFocusChange;
EditText.AddTextChangedListener(this);
EditText.SetOnEditorActionListener(this);
EditText.ImeOptions = ImeAction.Done;
SetText();
SetHintText();
SetErrorText();
SetFontAttributesSizeAndFamily();
SetInputType();
SetTextColor();
SetHorizontalTextAlignment();
SetFloatingHintEnabled();
SetIsEnabled();
SetErrorDisplay();
SetLabelAndUnderlineColor();
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == Entry.PlaceholderProperty.PropertyName)
SetHintText();
else if (e.PropertyName == XfxEntry.ErrorTextProperty.PropertyName)
SetErrorText();
else if (e.PropertyName == Entry.IsPasswordProperty.PropertyName ||
e.PropertyName == InputView.KeyboardProperty.PropertyName)
SetInputType();
else if (e.PropertyName == Entry.TextProperty.PropertyName)
SetText();
else if (e.PropertyName == Entry.HorizontalTextAlignmentProperty.PropertyName)
SetHorizontalTextAlignment();
else if (e.PropertyName == XfxEntry.FloatingHintEnabledProperty.PropertyName)
SetFloatingHintEnabled();
else if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
SetIsEnabled();
else if ((e.PropertyName == Entry.FontAttributesProperty.PropertyName) ||
(e.PropertyName == Entry.FontFamilyProperty.PropertyName) ||
(e.PropertyName == Entry.FontSizeProperty.PropertyName))
SetFontAttributesSizeAndFamily();
else if (e.PropertyName == XfxEntry.ActivePlaceholderColorProperty.PropertyName ||
e.PropertyName == Entry.PlaceholderColorProperty.PropertyName)
SetLabelAndUnderlineColor();
else if (e.PropertyName == Entry.TextColorProperty.PropertyName)
SetTextColor();
}
private void ControlOnFocusChange(object sender, FocusChangeEventArgs args)
{
_hasFocus = args.HasFocus;
if (_hasFocus)
{
var manager = (InputMethodManager)Application.Context.GetSystemService(Context.InputMethodService);
EditText.PostDelayed(() =>
{
EditText.RequestFocus();
manager.ShowSoftInput(EditText, 0);
},
100);
}
var isFocusedPropertyKey = Element.GetInternalField<BindablePropertyKey>("IsFocusedPropertyKey");
((IElementController)Element).SetValueFromRenderer(isFocusedPropertyKey, _hasFocus);
//This will change floating label entry SetUnderlineColor >>>> SetUnderlineColor color basedon focus or non focus
SetUnderlineColor(_hasFocus ? GetActivePlaceholderColor() : GetPlaceholderColor());
}
protected AColor GetPlaceholderColor() => Element.PlaceholderColor.ToAndroid(Color.FromHex("#80000000"));
private AColor GetActivePlaceholderColor() => Element.ActivePlaceholderColor.ToAndroid(global::Android.Resource.Attribute.ColorAccent, Context);
protected virtual void SetLabelAndUnderlineColor()
{
var defaultColor = GetPlaceholderColor();
var activeColor = GetActivePlaceholderColor();
SetHintLabelDefaultColor(defaultColor);
SetHintLabelActiveColor(activeColor);
SetUnderlineColor(_hasFocus ? activeColor : defaultColor);
}
//This will change entry under line color
private void SetUnderlineColor(AColor color)
{
var element = (ITintableBackgroundView)EditText;
element.SupportBackgroundTintList = ColorStateList.ValueOf(color);
}
private void SetHintLabelActiveColor(AColor color)
{
var hintText = Control.Class.GetDeclaredField("mFocusedTextColor");
hintText.Accessible = true;
hintText.Set(Control, new ColorStateList(new int[][] { new[] { 0 } }, new int[] { color }));
}
private void SetHintLabelDefaultColor(AColor color)
{
var hint = Control.Class.GetDeclaredField("mDefaultTextColor");
hint.Accessible = true;
hint.Set(Control, new ColorStateList(new int[][] { new[] { 0 } }, new int[] { color }));
}
private void SetText()
{
if (EditText.Text != Element.Text)
{
EditText.Text = Element.Text;
if (EditText.IsFocused)
EditText.SetSelection(EditText.Text.Length);
}
}
private void SetHintText()
{
Control.Hint = Element.Placeholder;
}
private void SetTextColor()
{
if (Element.TextColor == Color.Default)
{
EditText.SetTextColor(_defaultTextColor);
}
else
{
EditText.SetTextColor(Element.TextColor.ToAndroid());
}
}
private void SetHorizontalTextAlignment()
{
switch (Element.HorizontalTextAlignment)
{
case Xamarin.Forms.TextAlignment.Center:
EditText.Gravity = GravityFlags.CenterHorizontal;
break;
case Xamarin.Forms.TextAlignment.End:
EditText.Gravity = GravityFlags.Right;
break;
default:
EditText.Gravity = GravityFlags.Left;
break;
}
}
public void SetFloatingHintEnabled()
{
Control.HintEnabled = Element.FloatingHintEnabled;
Control.HintAnimationEnabled = Element.FloatingHintEnabled;
SetFontAttributesSizeAndFamily();
}
public void SetErrorDisplay()
{
switch (Element.ErrorDisplay)
{
case ErrorDisplay.None:
Control.ErrorEnabled = false;
break;
case ErrorDisplay.Underline:
Control.ErrorEnabled = true;
break;
}
}
protected void HideKeyboard()
{
var manager = (InputMethodManager)Application.Context.GetSystemService(Context.InputMethodService);
manager.HideSoftInputFromWindow(EditText.WindowToken, 0);
}
//here we can set entry floating label >>> input text size
private void SetFontAttributesSizeAndFamily()
{
EditText.Typeface = Control.Typeface = Element.ToTypeface();
EditText.SetTextSize(ComplexUnitType.Sp, (float)Element.FontSize);
//var a = (float)Element.FontSize; //18
}
private void SetErrorText()
{
Control.Error = !string.IsNullOrEmpty(Element.ErrorText) ? Element.ErrorText : null;
}
private void SetIsEnabled()
{
EditText.Enabled = Element.IsEnabled;
}
private void SetInputType()
{
EditText.InputType = Element.Keyboard.ToInputType();
if (Element.IsPassword && (EditText.InputType & InputTypes.ClassText) == InputTypes.ClassText)
{
EditText.TransformationMethod = new PasswordTransformationMethod();
EditText.InputType = EditText.InputType | InputTypes.TextVariationPassword;
}
if (Element.IsPassword && (EditText.InputType & InputTypes.ClassNumber) == InputTypes.ClassNumber)
{
EditText.TransformationMethod = new PasswordTransformationMethod();
EditText.InputType = EditText.InputType | InputTypes.NumberVariationPassword;
}
}
}
}
XML : -
<xfx:XfxEntry x:Name="EntPassword" Placeholder="Password" IsPassword="True" Focused="EntPassword_Focused"></xfx:XfxEntry>
<Button Text="Sign Up" BackgroundColor="#C62729" TextColor="White" x:Name="BtnSignUp" Clicked="BtnSignUp_Clicked" ></Button>
Please help.
Thanks in advance