Reputation: 5628
How to bind a Time - & /DatePicker with MVVMCross in Mono For Android?
<TimePicker
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<DatePicker
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
And what are the types of the Properties behind? For Date, probably DateTime and for the TimePicker? Or do we have here a Property foreach Number, for Example for Date: Year (INT), Month (INT) and Day (INT) = 3 Properties?
Stuck at this one and didn't find any examples..
Help appreciated
Upvotes: 2
Views: 4247
Reputation: 66882
The DatePicker API from Android is pretty disgusting...
However, binding it should be pretty easy :)
What I would do is to add a custom control and a custom binding.
For some help on Custom Droid controls, see
For some other questions about Custom Bindings, see
and other links from http://slodge.blogspot.co.uk/p/mvvmcross-quicklist.html
The Android DatePicker
API was clearly written by Kermit during some downtime, so for the DatePicker
, I would probably suggest is that you implement an EmiDatePicker
that inherits from DatePicker
and tidies up the API.
This can provide a single property and a single event:
private bool _initialised;
public DateTime Value
{
get
{
return new DateTime(Year, Month.ToCLRMonthNumber(), DayOfMonth);
}
set
{
if (_initialised)
{
UpdateDate(value.Year, value.Month.ToJavaMonthNumber(), value.DayOfMonth);
}
else
{
_initialised = true;
Init(value.Year, value.Month.ToJavaMonthNumber(), value.DayOfMonth, new EmiListener(this));
}
}
}
public event EventHandler ValueChanged;
where:
ToJavaMonthNumber
, ToCLRMonthNumber
are workarounds for +1, -1 fixes - see MonthDisplayHelper.NumberOfDaysInMonth returning incorrect value in MonoDroidEmiListener is a simple implementation of IOnDateChangeListener
to fire ValueChanged - something like:
public class EmiListener : Java.Lang.Object, DatePicker.IOnDateChangedListener
{
private EmiDatePicker _datePicker;
public EmiListener(EmiDatePicker datePicker)
{
_datePicker = datePicker;
}
public void OnDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth)
{
_datePicker.InternalSetValueAndRaiseChanged(new DateTime(year, monthOfYear.ToCLRMonth(), dayOfMonth));
}
}
With this done... then the next code step would be to add a binding - this would be simple:
public class EmiDatePickerValueTargetBinding : MvxPropertyInfoTargetBinding<EmiDatePicker>
{
public EmiDatePickerValueTargetBinding(object target, PropertyInfo targetPropertyInfo)
: base(target, targetPropertyInfo)
{
var datePicker = View;
if (datePicker == null)
{
MvxBindingTrace.Trace(MvxTraceLevel.Error, "Error - datePicker is null in EmiDatePickerValueTargetBinding");
}
else
{
datePicker.ValueChanged += DatePickerOnValueChanged;
}
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.TwoWay; }
}
private void DatePickerOnValueChanged(object sender, EventArgs args)
{
FireValueChanged(View.Value);
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (isDisposing)
{
var datePicker = View;
if (datePicker != null)
{
datePicker.ValueChanged -= DatePickerOnValueChanged;
}
}
}
}
And to register this binding, just add it in your app's setup class:
protected override void FillTargetFactories(Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target.Construction.IMvxTargetBindingFactoryRegistry registry)
{
registry.RegisterFactory(new MvxSimplePropertyInfoTargetBindingFactory(
typeof (EmiDatePickerValueTargetBinding), typeof (EmiDatePicker), "Value"));
base.FillTargetFactories(registry);
}
At this point, you can finally just use an EmiDatePicker in your XML - although to save on typing I'd recommend using an XML abbreviation - http://slodge.blogspot.co.uk/2013/02/abbreviated-namespaces-for-your-custom.html
To do TimePicker... same again, but I'll leave that to you...
There will be typos in the above code - please do edit it to correct it.
If this code works... and since it is a lot of 'mechanical code', I would love to see it open-sourced (maybe even pushed back to MvvmCross)
Upvotes: 1