Describe the bug
The app crashes when the plugin Calendar is used with Cultures whose AbbreviatedDayNames are not all the same length, DaysTitleMaximumLength is not explicitly set, and the shortest name has a char count lower than 3 characters (e.g. Hungarian, Belarusian, Maori, ...), resulting in
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentOutOfRangeException: Index and length must refer to a location within the string.
To Reproduce
Steps to reproduce the behavior:
Bind the Culture of the Calendar control to a variable set to -for instance- Hungarian (hu).
Do not set the DaysTitleMaximumLength property (defaults to 3), or set it to 2.
Expected behavior
The app should not crash and the calendar should show the day names up to the min between DaysTitleMaximumLength and the day name length itself.
Version information:
Plugin version: 1.2.2936
Platform: Android and iOS
Additional context
The culprit of the crash is located at this very line of code as of the complete stacktrace:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentOutOfRangeException: Index and length must refer to a location within the string.
Parameter name: length
at System.String.Substring (System.Int32 startIndex, System.Int32 length) [0x0004c] in <5e301229c46f4675aa8af93f827c14a9>:0
at Xamarin.Plugin.Calendar.Controls.MonthDaysView.UpdateDayTitles () [0x0004d] in <11a4cfdcbc214d80a40fff879666004e>:0
at Xamarin.Plugin.Calendar.Controls.MonthDaysView.OnPropertyChanged (System.String propertyName) [0x00294] in <11a4cfdcbc214d80a40fff879666004e>:0
at Xamarin.Forms.BindableObject.SetValueActual (Xamarin.Forms.BindableProperty property, Xamarin.Forms.BindableObject+BindablePropertyContext context, System.Object value, System.Boolean currentlyApplying, Xamarin.Forms.Internals.SetValueFlags attributes, System.Boolean silent) [0x0011b] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindableObject.SetValueCore (Xamarin.Forms.BindableProperty property, System.Object value, Xamarin.Forms.Internals.SetValueFlags attributes, Xamarin.Forms.BindableObject+SetValuePrivateFlags privateAttributes) [0x00173] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindingExpression.ApplyCore (System.Object sourceObject, Xamarin.Forms.BindableObject target, Xamarin.Forms.BindableProperty property, System.Boolean fromTarget) [0x00214] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindingExpression.Apply (System.Boolean fromTarget) [0x0003e] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindingExpression+BindingExpressionPart.<PropertyChanged>b__49_0 () [0x00000] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindingExpression+BindingExpressionPart.PropertyChanged (System.Object sender, System.ComponentModel.PropertyChangedEventArgs args) [0x000cb] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindingExpression+WeakPropertyChangedProxy.OnPropertyChanged (System.Object sender, System.ComponentModel.PropertyChangedEventArgs e) [0x00012] in <90d760e930d94d67861701555b251ae9>:0
at (wrapper delegate-invoke) <Module>.invoke_void_object_PropertyChangedEventArgs(object,System.ComponentModel.PropertyChangedEventArgs)
at Xamarin.Forms.BindableObject.OnPropertyChanged (System.String propertyName) [0x00012] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.Element.OnPropertyChanged (System.String propertyName) [0x00000] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Plugin.Calendar.Controls.Calendar.OnPropertyChanged (System.String propertyName) [0x00000] in <11a4cfdcbc214d80a40fff879666004e>:0
at Xamarin.Forms.BindableObject.SetValueActual (Xamarin.Forms.BindableProperty property, Xamarin.Forms.BindableObject+BindablePropertyContext context, System.Object value, System.Boolean currentlyApplying, Xamarin.Forms.Internals.SetValueFlags attributes, System.Boolean silent) [0x0011b] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindableObject.SetValueCore (Xamarin.Forms.BindableProperty property, System.Object value, Xamarin.Forms.Internals.SetValueFlags attributes, Xamarin.Forms.BindableObject+SetValuePrivateFlags privateAttributes) [0x00173] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindingExpression.ApplyCore (System.Object sourceObject, Xamarin.Forms.BindableObject target, Xamarin.Forms.BindableProperty property, System.Boolean fromTarget) [0x00214] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindingExpression.Apply (System.Object sourceObject, Xamarin.Forms.BindableObject target, Xamarin.Forms.BindableProperty property) [0x0006b] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.Binding.Apply (System.Object context, Xamarin.Forms.BindableObject bindObj, Xamarin.Forms.BindableProperty targetProperty, System.Boolean fromBindingContextChanged) [0x0006d] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindableObject.ApplyBindings (System.Boolean skipBindingContext, System.Boolean fromBindingContextChanged) [0x00049] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindableObject.SetInheritedBindingContext (Xamarin.Forms.BindableObject bindable, System.Object value) [0x0005a] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.Element.SetChildInheritedBindingContext (Xamarin.Forms.Element child, System.Object context) [0x00000] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.TemplatedView.SetChildInheritedBindingContext (Xamarin.Forms.Element child, System.Object context) [0x00008] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.Element.<OnBindingContextChanged>b__82_0 (Xamarin.Forms.BindableObject child, System.Object bc) [0x00000] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindableObjectExtensions.PropagateBindingContext[T] (Xamarin.Forms.BindableObject self, System.Collections.Generic.IList`1[T] children, System.Action`2[T1,T2] setChildBindingContext) [0x0002c] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.Element.OnBindingContextChanged () [0x00007] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.VisualElement.OnBindingContextChanged () [0x00006] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.View.OnBindingContextChanged () [0x0000c] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.ContentView.OnBindingContextChanged () [0x00000] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindableObject.SetInheritedBindingContext (Xamarin.Forms.BindableObject bindable, System.Object value) [0x00062] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.Element.SetChildInheritedBindingContext (Xamarin.Forms.Element child, System.Object context) [0x00000] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.Element.<OnBindingContextChanged>b__82_0 (Xamarin.Forms.BindableObject child, System.Object bc) [0x00000] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindableObjectExtensions.PropagateBindingContext[T] (Xamarin.Forms.BindableObject self, System.Collections.Generic.IList`1[T] children, System.Action`2[T1,T2] setChildBindingContext) [0x0002c] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.Element.OnBindingContextChanged () [0x00007] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.VisualElement.OnBindingContextChanged () [0x00006] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.View.OnBindingContextChanged () [0x0000c] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.Grid.OnBindingContextChanged () [0x00006] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindableObject.SetInheritedBindingContext (Xamarin.Forms.BindableObject bindable, System.Object value) [0x00062] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.Element.SetChildInheritedBindingContext (Xamarin.Forms.Element child, System.Object context) [0x00000] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.TemplatedPage.SetChildInheritedBindingContext (Xamarin.Forms.Element child, System.Object context) [0x00008] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.Element.<OnBindingContextChanged>b__82_0 (Xamarin.Forms.BindableObject child, System.Object bc) [0x00000] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindableObjectExtensions.PropagateBindingContext[T] (Xamarin.Forms.BindableObject self, System.Collections.Generic.IList`1[T] children, System.Action`2[T1,T2] setChildBindingContext) [0x0002c] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.Element.OnBindingContextChanged () [0x00007] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.VisualElement.OnBindingContextChanged () [0x00006] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.Page.OnBindingContextChanged () [0x00000] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.ContentPage.OnBindingContextChanged () [0x00000] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindableObject.BindingContextPropertyChanged (Xamarin.Forms.BindableObject bindable, System.Object oldvalue, System.Object newvalue) [0x0000f] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindableObject.SetValueActual (Xamarin.Forms.BindableProperty property, Xamarin.Forms.BindableObject+BindablePropertyContext context, System.Object value, System.Boolean currentlyApplying, Xamarin.Forms.Internals.SetValueFlags attributes, System.Boolean silent) [0x0012a] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindableObject.SetValueCore (Xamarin.Forms.BindableProperty property, System.Object value, Xamarin.Forms.Internals.SetValueFlags attributes, Xamarin.Forms.BindableObject+SetValuePrivateFlags privateAttributes) [0x00173] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindableObject.SetValue (Xamarin.Forms.BindableProperty property, System.Object value, System.Boolean fromStyle, System.Boolean checkAccess) [0x00042] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindableObject.SetValue (Xamarin.Forms.BindableProperty property, System.Object value) [0x00000] in <90d760e930d94d67861701555b251ae9>:0
at Xamarin.Forms.BindableObject.set_BindingContext (System.Object value) [0x00000] in <90d760e930d94d67861701555b251ae9>:0
at InimFireApp.Views.CalendarPage.set_ViewModel (InimFireApp.Views.CalendarPage value) [0x00000] in <dde3778d17404487980f1ba1beb75ed0>:0
at InimFireApp.Views.CalendarPage..ctor () [0x0009c] in <dde3778d17404487980f1ba1beb75ed0>:0
at (wrapper managed-to-native) System.Reflection.RuntimeConstructorInfo.InternalInvoke(System.Reflection.RuntimeConstructorInfo,object,object[],System.Exception&)
at System.Reflection.RuntimeConstructorInfo.InternalInvoke (System.Object obj, System.Object[] parameters, System.Boolean wrapExceptions) [0x00005] in <5e301229c46f4675aa8af93f827c14a9>:0
A possible fix could be to change the Substring to
Please Note that it may not suffice if the same happens elsewhere in the plugin code.
Workaround
Set DaysTitleMaximumLength to 1 (not always ideal)
Bind the DaysTitleMaximumLength property of the Calendar to a getter field in your ViewModel in which, known your "CurrentCulture" you do the following:
get
{
int dayMaxLength = 3;
foreach (var day in CurrentCulture.DateTimeFormat.AbbreviatedDayNames)
{
if (day.Length < dayMaxLength)
dayMaxLength = day.Length;
}
return (Xamarin.Plugin.Calendar.DaysTitleMaxLength)dayMaxLength;
}
Describe the bug The app crashes when the plugin Calendar is used with Cultures whose AbbreviatedDayNames are not all the same length, DaysTitleMaximumLength is not explicitly set, and the shortest name has a char count lower than 3 characters (e.g. Hungarian, Belarusian, Maori, ...), resulting in
To Reproduce Steps to reproduce the behavior:
Expected behavior The app should not crash and the calendar should show the day names up to the min between DaysTitleMaximumLength and the day name length itself.
Version information:
Additional context The culprit of the crash is located at this very line of code as of the complete stacktrace:
A possible fix could be to change the Substring to
Please Note that it may not suffice if the same happens elsewhere in the plugin code.
Workaround