This is a migrated thread and some comments may be shown as answers.

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

3 Answers 129 Views
DataForm
This is a migrated thread and some comments may be shown as answers.
Greg Lavelle
Top achievements
Rank 1
Greg Lavelle asked on 04 May 2017, 04:21 PM

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

3 Answers, 1 is accepted

Sort by
0
Lance | Manager Technical Support
Telerik team
answered on 05 May 2017, 01:44 PM
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
0
Greg Lavelle
Top achievements
Rank 1
answered on 08 May 2017, 10:18 AM

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

0
Ivaylo Gergov
Telerik team
answered on 11 May 2017, 08:09 AM
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
Tags
DataForm
Asked by
Greg Lavelle
Top achievements
Rank 1
Answers by
Lance | Manager Technical Support
Telerik team
Greg Lavelle
Top achievements
Rank 1
Ivaylo Gergov
Telerik team
Share this question
or