Completed
Last Updated: 20 Dec 2021 12:54 by ADMIN
Release R1 2022
ebrahim
Created on: 10 Dec 2021 10:19
Category: Calendar
Type: Bug Report
1
RadDateTimePicker: ArgumentOutOfRangeException with PersianCalendar "Day must be between 1 and 29 for month 12"

Run the attached sample project and try entering "1400/12/30".

            CultureInfo info = new CultureInfo("fa-Ir");

            this.radDateTimePicker1.Format = DateTimePickerFormat.Custom;
            this.radDateTimePicker1.CustomFormat = "yyyy/MM/dd";
            this.radDateTimePicker1.Culture = info;

The following exception occurs: 

   at System.Globalization.PersianCalendar.ToDateTime(Int32 year, Int32 month, Int32 day, Int32 hour, Int32 minute, Int32 second, Int32 millisecond, Int32 era)
   at System.Globalization.Calendar.ToDateTime(Int32 year, Int32 month, Int32 day, Int32 hour, Int32 minute, Int32 second, Int32 millisecond)
   at Telerik.WinControls.UI.ArabicMaskDateTimeProvider.KeyPress(Object sender, KeyPressEventArgs e)
   at Telerik.WinControls.UI.RadMaskedEditBoxElement.TextBoxItem_KeyPress(Object sender, KeyPressEventArgs e)
   at System.Windows.Forms.KeyPressEventHandler.Invoke(Object sender, KeyPressEventArgs e)
   at Telerik.WinControls.RadItem.OnKeyPress(KeyPressEventArgs e)
   at Telerik.WinControls.UI.RadTextBoxItem.TextBoxControl_KeyPress(Object sender, KeyPressEventArgs e)
   at System.Windows.Forms.Control.OnKeyPress(KeyPressEventArgs e)
   at System.Windows.Forms.Control.ProcessKeyEventArgs(Message& m)
   at System.Windows.Forms.Control.ProcessKeyMessage(Message& m)
   at System.Windows.Forms.Control.WmKeyChar(Message& m)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.TextBoxBase.WndProc(Message& m)
   at System.Windows.Forms.TextBox.WndProc(Message& m)
   at Telerik.WinControls.UI.HostedTextBoxBase.WndProc(Message& message)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
   at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.Run(Form mainForm)
   at DateTimePickerPersianCalendar.Program.Main() in c:\Projects\DateTimePickerPersianCalendar\DateTimePickerPersianCalendar\Program.cs:line 17
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

 

1 comment
ADMIN
Dess | Tech Support Engineer, Principal
Posted on: 10 Dec 2021 10:48

Hi, Ebrahim,

Thank you for reporting this. I have also updated your Telerik points.

Currently, the possible solution that I can suggest is to use the following custom provider:

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            ArabicMaskDateTimeProvider dateTimeProvider = new CustomArabicMaskDateTimeProvider(this.radDateTimePicker1.DateTimePickerElement.TextBoxElement.Provider.Mask
               , info, this.radDateTimePicker1.DateTimePickerElement.TextBoxElement);
            this.radDateTimePicker1.DateTimePickerElement.TextBoxElement.Provider = dateTimeProvider;
        }
        public class CustomArabicMaskDateTimeProvider : ArabicMaskDateTimeProvider
        { 
            public CustomArabicMaskDateTimeProvider(string mask, CultureInfo info, RadMaskedEditBoxElement owner)
                : base(mask, info, owner)
            {

            } 

            public override void KeyPress(object sender, KeyPressEventArgs e)
            {
                System.Reflection.FieldInfo fi = typeof(MaskDateTimeProvider).GetField("value", BindingFlags.NonPublic | BindingFlags.Instance);
                DateTime value = (DateTime)fi.GetValue(this);
                if (e.Handled)
                {
                    return;
                }

                MaskPart part = this.List[this.SelectedItemIndex];
                if ("\\/-:,.".IndexOf(e.KeyChar) > -1)
                {
                    int index = this.TextBoxItem.Text.IndexOf(e.KeyChar, this.TextBoxItem.SelectionStart);
                    if (index == -1)
                    {
                        index = this.TextBoxItem.Text.IndexOf(e.KeyChar, 0);
                    }
                    if (index == -1)
                    {
                        e.Handled = true;
                        return;
                    }

                    if (this.EnableKeyNavigation)
                    {
                        this.TextBoxItem.SelectionStart = index;
                        this.SelectNextEditableItemFromCurrentCaret();
                    }

                    e.Handled = true;
                    return;
                }

                if (part.readOnly)
                {
                    e.Handled = true;
                    return;
                }

                if (this.SelectedItemIndex != this.oldSelectedIndex)
                {
                    this.keyCounter = 0;
                    this.oldSelectedIndex = this.SelectedItemIndex;
                }

                if (this.ResetOnDelPartValue(part, e.KeyChar))
                {
                    e.Handled = true;
                }

                switch (part.type)
                {
                    case PartTypes.ReadOnly:
                        break;
                    case PartTypes.Day:
                        int partValue = part.value;
                        part = this.SetDayMaxValue(this.List);
                        part.value = partValue;
                        this.HandleKeyPressDay(part, e);
                        part.Validate();
                        if (part.value == 0)
                        {
                            part.value = 1;
                        }
                        int maxDays = 29;
                        try
                        {
                            maxDays = this.Culture.Calendar.GetDaysInMonth(this.Culture.Calendar.GetYear(value), this.Culture.Calendar.GetMonth(value));
                        }
                        catch (ArgumentOutOfRangeException)
                        {
                        }
                        if (part.value > maxDays)
                        {
                            part.value = maxDays;
                        }

                        this.Value = this.Culture.Calendar.ToDateTime(this.Culture.Calendar.GetYear(value), this.Culture.Calendar.GetMonth(value),
                            part.value, value.Hour, value.Minute, value.Second, value.Millisecond);

                        if (char.IsLetterOrDigit(e.KeyChar))
                        {
                            ++this.keyCounter;
                        }
                        break;
                    case PartTypes.MiliSeconds:
                        this.HandleKeyPress(part, e);
                        part.Validate();
                        int newValue = (int)(part.value * Math.Pow(10, 3 - part.len));
                        this.Value = new DateTime(value.Year, value.Month, value.Day, value.Hour, value.Minute,
                            value.Second, (newValue > part.max) ? part.value : newValue);
                        if (char.IsDigit(e.KeyChar))
                        {
                            ++this.keyCounter;
                        }
                        break;
                    case PartTypes.h12:
                    case PartTypes.h24:
                        this.HandleKeyPressHour(part, e);
                        this.Value = new DateTime(value.Year, value.Month, value.Day, part.value, value.Minute, value.Second, value.Millisecond);
                        if (char.IsLetterOrDigit(e.KeyChar))
                        {
                            ++this.keyCounter;
                        }
                        break;
                    case PartTypes.Minutes:
                        this.HandleKeyPress(part, e);
                        part.Validate();
                        this.Value = new DateTime(value.Year, value.Month, value.Day, value.Hour,
                            part.value, value.Second, value.Millisecond);
                        if (char.IsDigit(e.KeyChar))
                        {
                            ++this.keyCounter;
                        }

                        break;
                    case PartTypes.Month:
                        this.HandleMonthKeyPress(e, part);
                        part.Validate();

                        MaskPart dayPart = this.SetDayMaxValue(this.List);
                        int dayPartValue = value.Day;
                        if (dayPart != null)
                        {
                            dayPartValue = dayPart.value;
                        }

                        DateTime? tryDate = null;
                        string monthProbing = part.value < 10 ? string.Format("0{0}", part.value.ToString()) : part.value.ToString();
                        for (int month = 1; month < 12; ++month)
                        {
                            string monthName = null;
                            try
                            {
                                tryDate = this.Culture.Calendar.ToDateTime(this.Culture.Calendar.GetYear(value), part.value,
                                    dayPartValue, value.Hour, value.Minute, value.Second, value.Millisecond);
                                if (tryDate.HasValue)
                                {
                                    monthName = tryDate.Value.ToString("MM", this.Culture);
                                }
                            }
                            catch (ArgumentOutOfRangeException)
                            {
                            }

                            if (monthProbing == monthName)
                            {
                                part.value = month;
                                break;
                            }

                        }
                        if (tryDate.HasValue)
                        {
                            fi.SetValue(this, tryDate.Value);
                            // this.value = tryDate.Value;
                        }

                        this.Value = this.Culture.Calendar.ToDateTime(this.Culture.Calendar.GetYear(value), part.value, dayPartValue,
                            value.Hour, value.Minute, value.Second, value.Millisecond);
                        if (char.IsDigit(e.KeyChar))
                        {
                            ++this.keyCounter;
                        }

                        break;
                    case PartTypes.Seconds:
                        this.HandleKeyPress(part, e);
                        part.Validate();
                        this.Value = new DateTime(value.Year, value.Month, value.Day, value.Hour, value.Minute, part.value, value.Millisecond);
                        if (char.IsLetterOrDigit(e.KeyChar))
                        {
                            ++this.keyCounter;
                        }
                        break;
                    case PartTypes.AmPm:
                        this.HandleAmPmKeyPress(e);
                        if (char.IsLetterOrDigit(e.KeyChar))
                        {
                            ++this.keyCounter;
                        }
                        break;
                    case PartTypes.Year:
                        bool ready = this.HandleKeyPress(part, e);
                        if (!ready)
                        {
                            return;
                        }
                        this.keyCounter = 0;
                        part.Validate();
                        MaskPart dayPart1 = this.SetDayMaxValue(this.List);
                        int dayPartValue1 = value.Day;
                        if (dayPart1 != null)
                        {
                            dayPartValue1 = dayPart1.value;
                        }
                        try
                        {
                            this.Value = this.Culture.Calendar.ToDateTime(part.value, this.Culture.Calendar.GetMonth(value),
                                this.Culture.Calendar.GetDayOfMonth(value), value.Hour, value.Minute, value.Second, value.Millisecond);
                        }
                        catch (ArgumentOutOfRangeException)
                        {
                        }

                        break;
                    case PartTypes.Character:
                        break;
                    default:
                        break;
                }

                e.Handled = true;
                this.FillCollectionWithValues(this.List, value, this.Mask);
                if (!this.AutoSelectNextPart)
                {
                    this.RestoreSelectedItem();
                }
                else if (this.keyCounter >= part.len)
                {
                    if (part.type == PartTypes.Day ||
                        part.type == PartTypes.Month ||
                        part.type == PartTypes.h12 ||
                        part.type == PartTypes.h24)
                    {
                        if (this.keyCounter >= 2)//these mask types must be at least 2 characters long in order to select next part
                        {
                            this.SelectNextEditableItem();
                            this.keyCounter = 0;
                        }

                        return;
                    }

                    this.SelectNextEditableItem();
                    this.keyCounter = 0;
                }
            }
        }

I hope this information helps. If you need any further assistance please don't hesitate to contact me. 

Regards,
Dess | Tech Support Engineer, Principal
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.