Using Date/TimePicker with string backing object - Third party source

4 posts, 0 answers
  1. Greg Lavelle
    Greg Lavelle avatar
    6 posts
    Member since:
    Oct 2006

    Posted 04 May Link to this post

    Good evening,

    I am trying to get working date fields and the "third party source" (no decorations) way to generate a dataform but I just can't figure out how to solve this. I have read the documentation about the dataform and made some tests to adapt the code e.g. for the custom string DateTime converter.

    I took the Telerik example in \Examples\XamarinForms\SDKBrowser\SDKBrowser\Examples\DataForm\DataFormCustomSource.xaml as a base and added a "Date" field inside the source dictionary.
    I registered the date editor for the field after setting the source and also set some metadata for the field (a custom string DateTime converter, the DateRangeValidatorAttribute validator and the NativeConversionContext = DateTimeKind.Utc) but the code crashes before displaying the dataform. There is no other code changes.

    How is it possible to achieve this?

    When I load the data form, the debugger goes through the converter Convert method without problem before crashing. Here is the Exception I have:

    Java.Lang.Error: DataFormDateEditor does not support properties of type String. Please specify a value converter for your property. ---> Java.Lang.ClassCastException: java.util.GregorianCalendar cannot be cast to java.lang.Number
       --- End of inner exception stack trace ---
      at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Users/builder/data/lanes/4009/3a62f1ea/source/mono/mcs/class/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:143
      at Java.Interop.JniEnvironment+InstanceMethods.CallVoidMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x00084] in /Users/builder/data/lanes/4009/3a62f1ea/source/Java.Interop/src/Java.Interop/Java.Interop/JniEnvironment.g.cs:11643
      at Android.Runtime.JNIEnv.CallVoidMethod (System.IntPtr jobject, System.IntPtr jmethod, Android.Runtime.JValue* parms) [0x00000] in /Users/builder/data/lanes/4009/3a62f1ea/source/monodroid/src/Mono.Android/JNIEnv.g.cs:264
      at Com.Telerik.Widget.Dataform.Visualization.RadDataForm.set_Entity (Com.Telerik.Widget.Dataform.Engine.IEntity value) [0x00067] in <ae3a3c051b4c45cab0d27f8036263c89>:0
      at Telerik.XamarinForms.InputRenderer.Android.DataFormAdapter.UpdateEntity (Telerik.XamarinForms.Input.RadDataForm sourceOwner, Com.Telerik.Widget.Dataform.Visualization.RadDataForm targetOwner) [0x0003a] in <baeb1b2081654501888ace4ddb013183>:0
      at Telerik.XamarinForms.InputRenderer.Android.DataFormAdapter.UpdateCore (Telerik.XamarinForms.Input.RadDataForm sourceOwner, Com.Telerik.Widget.Dataform.Visualization.RadDataForm targetOwner, System.String propertyName) [0x0001d] in <baeb1b2081654501888ace4ddb013183>:0
      at Telerik.XamarinForms.Common.FacadeAdapterBase`2[S,T].Update (System.Object sourceOwner, System.Object targetOwner, System.String propertyName, System.Object sourceOwnerRoot, System.Object targetOwnerRoot) [0x00000] in <b09df7d4d5e74454b9482f9e64875b96>:0
      at Telerik.XamarinForms.Common.XamarinToNativeControlExtensions.Update[T,K] (T nativeElement, K xfЕlement, System.String propertyName, System.Object sourceOwnerRoot, System.Object targetOwnerRoot) [0x0002b] in <b09df7d4d5e74454b9482f9e64875b96>:0
      at Telerik.XamarinForms.InputRenderer.Android.DataFormRenderer.OnElementAttached (Telerik.XamarinForms.Input.RadDataForm newElement) [0x00032] in <baeb1b2081654501888ace4ddb013183>:0
      at Telerik.XamarinForms.Common.Android.AndroidRendererBase`2[S,T].OnElementChanged (Xamarin.Forms.Platform.Android.ElementChangedEventArgs`1[TElement] e) [0x00037] in <abbc9cd0d37b4c7ca6ff11fd056edf7f>:0
      at Xamarin.Forms.Platform.Android.VisualElementRenderer`1[TElement].SetElement (TElement element) [0x000f4] in C:\BuildAgent3\work\ca3766cfc22354a1\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:196
      at Xamarin.Forms.Platform.Android.VisualElementRenderer`1[TElement].Xamarin.Forms.Platform.Android.IVisualElementRenderer.SetElement (Xamarin.Forms.VisualElement element) [0x00027] in C:\BuildAgent3\work\ca3766cfc22354a1\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:137
      at Xamarin.Forms.Platform.Android.Platform.CreateRenderer (Xamarin.Forms.VisualElement element) [0x0001f] in C:\BuildAgent3\work\ca3766cfc22354a1\Xamarin.Forms.Platform.Android\Platform.cs:289
      at Xamarin.Forms.Platform.Android.VisualElementPackager.AddChild (Xamarin.Forms.VisualElement view, Xamarin.Forms.Platform.Android.IVisualElementRenderer oldRenderer, Xamarin.Forms.Platform.Android.RendererPool pool, System.Boolean sameChildren) [0x00023] in C:\BuildAgent3\work\ca3766cfc22354a1\Xamarin.Forms.Platform.Android\VisualElementPackager.cs:84
      at Xamarin.Forms.Platform.Android.VisualElementPackager.SetElement (Xamarin.Forms.VisualElement oldElement, Xamarin.Forms.VisualElement newElement) [0x00104] in C:\BuildAgent3\work\ca3766cfc22354a1\Xamarin.Forms.Platform.Android\VisualElementPackager.cs:217
      at Xamarin.Forms.Platform.Android.VisualElementPackager.Load () [0x00000] in C:\BuildAgent3\work\ca3766cfc22354a1\Xamarin.Forms.Platform.Android\VisualElementPackager.cs:68
      at Xamarin.Forms.Platform.Android.VisualElementRenderer`1[TElement].SetPackager (Xamarin.Forms.Platform.Android.VisualElementPackager packager) [0x00007] in C:\BuildAgent3\work\ca3766cfc22354a1\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:335
      at Xamarin.Forms.Platform.Android.VisualElementRenderer`1[TElement].SetElement (TElement element) [0x00111] in C:\BuildAgent3\work\ca3766cfc22354a1\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:199
      at Xamarin.Forms.Platform.Android.VisualElementRenderer`1[TElement].Xamarin.Forms.Platform.Android.IVisualElementRenderer.SetElement (Xamarin.Forms.VisualElement element) [0x00027] in C:\BuildAgent3\work\ca3766cfc22354a1\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:137
      at Xamarin.Forms.Platform.Android.Platform.CreateRenderer (Xamarin.Forms.VisualElement element, Android.Support.V4.App.FragmentManager fragmentManager) [0x00031] in C:\BuildAgent3\work\ca3766cfc22354a1\Xamarin.Forms.Platform.Android\Platform.cs:325
      at Xamarin.Forms.Platform.Android.AppCompat.FragmentContainer.OnCreateView (Android.Views.LayoutInflater inflater, Android.Views.ViewGroup container, Android.OS.Bundle savedInstanceState) [0x00008] in C:\BuildAgent3\work\ca3766cfc22354a1\Xamarin.Forms.Platform.Android\AppCompat\FragmentContainer.cs:67
      at Android.Support.V4.App.Fragment.n_OnCreateView_Landroid_view_LayoutInflater_Landroid_view_ViewGroup_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_inflater, System.IntPtr native_container, System.IntPtr native_savedInstanceState) [0x00022] in <27c17fe440cf491ba8255bcefade6e02>:0
      at (wrapper dynamic-method) System.Object:8b7a6b9b-c5f7-4699-a0b0-ed94f89278f8 (intptr,intptr,intptr,intptr,intptr)
      --- End of managed Java.Lang.Error stack trace ---

    Information:
    OS: Win10 Pro 64bits 1511
    Visual Studio 2015 Community: 14.25431.01 Update 3
    Telerik: 2017.1.10321.10
    Xamarin: 2.3.4.231
    PCL: profile 111

    Thanks!

    Greg
  2. Lance | Tech Support Engineer, Sr.
    Admin
    Lance | Tech Support Engineer, Sr. avatar
    419 posts

    Posted 05 May Link to this post

    Hello Greg,

    Set the source after registering your editors.

    For example:

    dataForm.RegisterEditor(nameof(SourceItem.Age), EditorType.IntegerEditor);
    dataForm.RegisterEditor(nameof(SourceItem.DateOfBirth), EditorType.MyCustomEditor);
     
    dataForm.Source = new Person();


    If this solves it, you can let me know by clicking the ticket's "Mark as Resolved" button. If it doesn't, please reply back with the all the code responsible so I can use to reproduce and debug the problem.

    Thank you for contacting Support and for choosing UI for Xamarin.

    Regards,
    Lance | Tech Support Engineer, Sr.
    Telerik by Progress
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  3. Greg Lavelle
    Greg Lavelle avatar
    6 posts
    Member since:
    Oct 2006

    Posted 08 May in reply to Lance | Tech Support Engineer, Sr. Link to this post

    Hello Lance,

    Thanks for your quick answer but it does not solve the issue. I still have the same exception.

    Here is the XAML code:

    01.<?xml version="1.0" encoding="utf-8" ?>
    03.             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    04.             x:Class="Telerik.DataForm.Test.DataFormPage"
    05.             xmlns:telerikInput="clr-namespace:Telerik.XamarinForms.Input;assembly=Telerik.XamarinForms.Input"
    06.             Title="Detailed Form">
    07.    <ContentPage.Content>
    08.        <telerikInput:RadDataForm x:Name="_dataForm">
    09.        </telerikInput:RadDataForm>
    10.    </ContentPage.Content>
    11.</ContentPage>

    Here is the code behind:

    001.using System;
    002.using System.Collections.Generic;
    003.using Xamarin.Forms;
    004.using Xamarin.Forms.Xaml;
    005.using Telerik.XamarinForms.Common.DataAnnotations;
    006.using Telerik.XamarinForms.Input.DataForm;
    007.using Telerik.XamarinForms.Input;
    008. 
    009.namespace Telerik.DataForm.Test
    010.{
    011.    [XamlCompilation(XamlCompilationOptions.Compile)]
    012.    public partial class DataFormPage : ContentPage
    013.    {
    014.        Dictionary<string, string> source = GetData();
    015. 
    016.        public DataFormPage()
    017.        {
    018.            InitializeComponent();
    019. 
    020.            _dataForm.MetadataProvider = new CustomMetadataProvider();
    021.             
    022.            _dataForm.RegisterEditor("Date", EditorType.DateEditor);
    023.            _dataForm.Source = source;
    024.        }
    025. 
    026.        private static Dictionary<string, string> GetData()
    027.        {
    028.            var dict = new Dictionary<string, string>();
    029. 
    030.            dict.Add("Text", "Some text");
    031.            dict.Add("Date", DateTime.UtcNow.ToString());
    032. 
    033.            return dict;
    034.        }
    035.    }
    036. 
    037.    public class CustomMetadataProvider : PropertyMetadataProviderBase
    038.    {
    039.        private List<IEntityProperty> entityProperties = new List<IEntityProperty>();
    040. 
    041.        public override List<IEntityProperty> EntityProperties { get { return entityProperties; } }
    042. 
    043.        public override void Initialize(object source)
    044.        {
    045.            var data = source as Dictionary<string, string>;
    046. 
    047.            foreach (var item in data)
    048.            {
    049.                var metadata = new EntityPropertyMetadata() { Header = item.Key };
    050. 
    051.                var now = DateTime.UtcNow;
    052.                switch (item.Key)
    053.                {
    054.                    case "Date":
    055.                        metadata.Converter = new DataFormStringDateTimeConverter();
    056.                        metadata.NativeConversionContext = DateTimeKind.Utc;
    057.                        //*
    058.                        metadata.Validators.Add(new DateRangeValidatorAttribute(now.Year
    059.                                                                                , now.Month
    060.                                                                                , now.Day
    061.                                                                                , DateTime.MaxValue.Year
    062.                                                                                , DateTime.MaxValue.Month
    063.                                                                                , DateTime.MaxValue.Day
    064.                                                                                , "You must enter a later date!")
    065.                                                                                );
    066.                        //*/
    067.                        break;
    068.                    default:
    069.                        break;
    070.                }
    071. 
    072.                var property = new CustomEntityProperty(item.Key, data, metadata);
    073.                this.entityProperties.Add(property);
    074.            }
    075.        }
    076.    }
    077. 
    078.    public class CustomEntityProperty : IEntityProperty
    079.    {
    080.        private Dictionary<string, string> dataItem;
    081. 
    082.        public CustomEntityProperty(string propertyName, Dictionary<string, string> item, EntityPropertyMetadata metadata)
    083.        {
    084.            this.PropertyName = propertyName;
    085.            this.PropertyType = item[propertyName].GetType();
    086.            this.Metadata = metadata;
    087.            this.dataItem = item;
    088.            this.IsReadOnly = false;
    089.        }
    090. 
    091.        public object OriginalValue
    092.        {
    093.            get
    094.            {
    095.                return this.dataItem[this.PropertyName];
    096.            }
    097.        }
    098. 
    099.        public Type PropertyType { get; }
    100. 
    101.        public EntityPropertyMetadata Metadata { get; }
    102. 
    103.        public object DataItem { get { return this.dataItem; } }
    104. 
    105.        public string PropertyName { get; }
    106. 
    107.        public object PropertyValue { get; set; }
    108. 
    109.        public bool IsReadOnly { get; }
    110. 
    111.        public void Commit()
    112.        {
    113.            this.dataItem[this.PropertyName] = (string)this.PropertyValue;
    114.        }
    115.    }
    116.     
    117.    /// <summary>
    118.    ///
    119.    /// </summary>
    120.    public class DataFormStringDateTimeConverter : IPropertyConverter
    121.    {
    122.        public object Convert(object value)
    123.        {
    124.            var dateTimeStr = value as string;
    125. 
    126.            DateTime dateTime;
    127. 
    128.            if (string.IsNullOrWhiteSpace(dateTimeStr) || !DateTime.TryParse(dateTimeStr, out dateTime)) return null;
    129. 
    130.            return dateTime;
    131.        }
    132. 
    133.        public object ConvertBack(object value)
    134.        {
    135.            var dateTime = value as DateTime?;
    136. 
    137.            if (!dateTime.HasValue) return null;
    138. 
    139.            var dateTimeStr = dateTime.Value.ToString("u");
    140. 
    141.            return dateTimeStr;
    142.        }
    143.    }
    144.}

    Regards,

    Greg

  4. Ivaylo Gergov
    Admin
    Ivaylo Gergov avatar
    691 posts

    Posted 11 May Link to this post

    Hello Greg,

    When creating the CustomEntityProperty make sure that you set the desired property type of the entity, i.e. for the Date property set DateTime instead of String. Thus, the entity will work with DateTime and when the DataForm tries to commit it will pass the DateTime value through the ConvertBack callback and everything should work as expected.
    While I was testing this scenario I found a bug in iOS related specifically to DateTime conversion(an exception is thrown).  I have applied a fix which will be available in our next release(somewhere after 19 May).

    I hope this helps. I have updated your Telerik points as a token of gratitude for the valuable feedback.

    Regards,
    Ivaylo Gergov
    Telerik by Progress
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Back to Top