2
votes

We are developing mobile application using Xamarin Forms framework (only targeting Android for now). We structured our application to utilize MVVM pattern with help of MVVMLight toolkit. For data management we are using BreezeSharp (as we already have Breeze friendly server implemented for web client).

The issue we are dealing with is application crash when typing in Xamarin Forms Entry control which is bound to property of Breeze entity.

Entry control in Xaml view:

<Entry Text="{Binding SelectedCustomerAddress.AddressLine1}" />

Property in ViewModel (Set() is from MVVMLight ViewModelBase):

public CustomerAddress SelectedCustomerAddress
{
    get { return this.selectedCustomerAddress; }
    set { this.Set(() => this.SelectedCustomerAddress, ref this.selectedCustomerAddress, value);}
}

Property in Breeze CLR type:

public string AddressLine1
{
    get { return this.GetValue<string>(); }
    set { this.SetValue(value); }
}

After typing only few characters in entry field, application would crash with stack trace:

11-10 11:51:02.896 F/        ( 4924): * Assertion at /Users/builder/data/lanes/monodroid-mlion-monodroid-4.18-series/3b7ef0a7/source/mono/mono/metadata/sgen-stw.c:68, condition `info->stack_start >= info->stack_start_limit && info->stack_start < info->stack_end' not met
11-10 11:51:02.900 E/mono-rt ( 4924): Stacktrace:
11-10 11:51:02.900 E/mono-rt ( 4924): 
11-10 11:51:02.904 E/mono-rt ( 4924):   at <unknown> <0xffffffff>
11-10 11:51:02.908 E/mono-rt ( 4924):   at (wrapper managed-to-native) object.MemberwiseClone (object) <IL 0x0002d, 0xffffffff>
11-10 11:51:02.912 E/mono-rt ( 4924):   at System.Delegate.Clone () <IL 0x00001, 0x00027>
11-10 11:51:02.916 E/mono-rt ( 4924):   at System.MulticastDelegate.CombineImpl (System.Delegate) <IL 0x000be, 0x0037c>
11-10 11:51:02.916 E/mono-rt ( 4924):   at System.Delegate.Combine (System.Delegate,System.Delegate) <IL 0x00062, 0x001f8>
11-10 11:51:02.920 E/mono-rt ( 4924):   at Breeze.Sharp.EntityAspect.add_EntityPropertyChanged (System.ComponentModel.PropertyChangedEventHandler) <IL 0x0000b, 0x00057>
11-10 11:51:02.924 E/mono-rt ( 4924):   at Breeze.Sharp.BaseEntity.System.ComponentModel.INotifyPropertyChanged.add_PropertyChanged (System.ComponentModel.PropertyChangedEventHandler) [0x00000] in c:\GitHub\breeze.sharp\Breeze.Sharp\BaseEntity.cs:74
11-10 11:51:02.928 E/mono-rt ( 4924):   at Xamarin.Forms.BindingExpression.ApplyCore (object,Xamarin.Forms.BindableObject,Xamarin.Forms.BindableProperty,bool) <IL 0x00130, 0x0077f>
11-10 11:51:02.928 E/mono-rt ( 4924):   at Xamarin.Forms.BindingExpression.Apply (bool) <IL 0x00041, 0x000f3>
11-10 11:51:02.932 E/mono-rt ( 4924):   at Xamarin.Forms.BindingExpression/BindingExpressionPart.<PropertyChanged>b__12 () <IL 0x00007, 0x0002f>
11-10 11:51:02.932 E/mono-rt ( 4924):   at Java.Lang.Thread/RunnableImplementor.Run () [0x0000b] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.18-series/3b7ef0a7/source/monodroid/src/Mono.Android/src/Java.Lang/Thread.cs:36
11-10 11:51:02.932 E/mono-rt ( 4924):   at Java.Lang.IRunnableInvoker.n_Run (intptr,intptr) [0x00009] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.18-series/3b7ef0a7/source/monodroid/src/Mono.Android/platforms/android-18/src/generated/Java.Lang.IRunnable.cs:71
11-10 11:51:02.932 E/mono-rt ( 4924):   at (wrapper dynamic-method) object.39beb2b5-65b4-431f-a21a-3e626049fa1f (intptr,intptr) <IL 0x00011, 0x0001b>
11-10 11:51:02.932 E/mono-rt ( 4924):   at (wrapper native-to-managed) object.39beb2b5-65b4-431f-a21a-3e626049fa1f (intptr,intptr) <IL 0x00022, 0xffffffff>
11-10 11:51:02.936 E/mono-rt ( 4924):   at <unknown> <0xffffffff>
11-10 11:51:02.936 E/mono-rt ( 4924):   at (wrapper managed-to-native) object.wrapper_native_0xb60a0eb0 (intptr,intptr,intptr,Android.Runtime.JValue[]) <IL 0x00120, 0xffffffff>
11-10 11:51:02.936 E/mono-rt ( 4924):   at Android.Runtime.JNIEnv.CallVoidMethod (intptr,intptr,Android.Runtime.JValue[]) [0x00040] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.18-series/3b7ef0a7/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:504
11-10 11:51:02.940 E/mono-rt ( 4924):   at Android.App.Activity.RunOnUiThread (Java.Lang.IRunnable) [0x0002d] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.18-series/3b7ef0a7/source/monodroid/src/Mono.Android/platforms/android-18/src/generated/Android.App.Activity.cs:4130
11-10 11:51:02.940 E/mono-rt ( 4924):   at Android.App.Activity.RunOnUiThread (System.Action) [0x00000] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.18-series/3b7ef0a7/source/monodroid/src/Mono.Android/src/Android.App/Activity.cs:23
11-10 11:51:02.940 E/mono-rt ( 4924):   at Xamarin.Forms.Forms/AndroidPlatformServices.BeginInvokeOnMainThread (System.Action) <IL 0x0000b, 0x00053>
11-10 11:51:02.940 E/mono-rt ( 4924):   at Xamarin.Forms.Device.BeginInvokeOnMainThread (System.Action) <IL 0x00006, 0x00038>
11-10 11:51:02.940 E/mono-rt ( 4924):   at Xamarin.Forms.BindingExpression/BindingExpressionPart.PropertyChanged (object,System.ComponentModel.PropertyChangedEventArgs) <IL 0x00087, 0x00313>
11-10 11:51:02.944 E/mono-rt ( 4924):   at (wrapper delegate-invoke) <Module>.invoke_void_object_PropertyChangedEventArgs (object,System.ComponentModel.PropertyChangedEventArgs) <IL 0x00027, 0x00042>
11-10 11:51:02.944 E/mono-rt ( 4924):   at (wrapper delegate-invoke) <Module>.invoke_void_object_PropertyChangedEventArgs (object,System.ComponentModel.PropertyChangedEventArgs) <IL 0x00027, 0x00042>
11-10 11:51:02.944 E/mono-rt ( 4924):   at (wrapper delegate-invoke) <Module>.invoke_void_object_PropertyChangedEventArgs (object,System.ComponentModel.PropertyChangedEventArgs) <IL 0x00027, 0x00042>

..... (2500 lines)

11-10 11:51:03.564 E/mono-rt ( 4924):   at (wrapper delegate-invoke) <Module>.invoke_void_object_PropertyChangedEventArgs (object,System.ComponentModel.PropertyChangedEventArgs) <IL 0x00059, 0xffffffff>
11-10 11:51:03.564 E/mono-rt ( 4924):   at Breeze.Sharp.EntityAspect.OnPropertyChangedCore (System.ComponentModel.PropertyChangedEventArgs) [0x0000b] in c:\GitHub\breeze.sharp\Breeze.Sharp\EntityAspect.cs:1315
11-10 11:51:03.564 E/mono-rt ( 4924):   at Breeze.Sharp.EntityAspect/<>c__DisplayClass4b.<OnPropertyChanged>b__4a () [0x00000] in c:\GitHub\breeze.sharp\Breeze.Sharp\EntityAspect.cs:1306
11-10 11:51:03.564 E/mono-rt ( 4924):   at Breeze.Sharp.EntityAspect.QueueEvent (System.Action) [0x0003e] in c:\GitHub\breeze.sharp\Breeze.Sharp\EntityAspect.cs:1362
11-10 11:51:03.564 E/mono-rt ( 4924):   at Breeze.Sharp.EntityAspect.OnPropertyChanged (System.ComponentModel.PropertyChangedEventArgs) [0x0003f] in c:\GitHub\breeze.sharp\Breeze.Sharp\EntityAspect.cs:1305
11-10 11:51:03.564 E/mono-rt ( 4924):   at Breeze.Sharp.EntityAspect.SetValueWithEvents<T> (T,object,System.Action`3<T, object, object>) [0x00042] in c:\GitHub\breeze.sharp\Breeze.Sharp\EntityAspect.cs:563
11-10 11:51:03.564 E/mono-rt ( 4924):   at Breeze.Sharp.EntityAspect.SetDpValue (Breeze.Sharp.DataProperty,object) [0x00000] in c:\GitHub\breeze.sharp\Breeze.Sharp\EntityAspect.cs:529
11-10 11:51:03.564 E/mono-rt ( 4924):   at Breeze.Sharp.EntityAspect.SetValue (Breeze.Sharp.StructuralProperty,object) [0x00052] in c:\GitHub\breeze.sharp\Breeze.Sharp\EntityAspect.cs:522
11-10 11:51:03.564 E/mono-rt ( 4924):   at Breeze.Sharp.EntityAspect.SetValue (string,object) [0x00031] in c:\GitHub\breeze.sharp\Breeze.Sharp\EntityAspect.cs:507
11-10 11:51:03.564 E/mono-rt ( 4924):   at Breeze.Sharp.BaseEntity.SetValue (object,string) [0x00000] in c:\GitHub\breeze.sharp\Breeze.Sharp\BaseEntity.cs:37
11-10 11:51:03.564 E/mono-rt ( 4924):   at Client.Common.Model.Proxy.CustomerAddress.set_AddressLine2 (string) [0x00001] in c:\Projects\Client\source\Client.Common\Model\Proxy\CustomerAddress.cs:26
11-10 11:51:03.564 E/mono-rt ( 4924):   at (wrapper runtime-invoke) <Module>.runtime_invoke_void__this___object (object,intptr,intptr,intptr) <IL 0x00052, 0xffffffff>
11-10 11:51:03.564 E/mono-rt ( 4924):   at <unknown> <0xffffffff>
11-10 11:51:03.564 E/mono-rt ( 4924):   at (wrapper managed-to-native) System.Reflection.MonoMethod.InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&) <IL 0x00030, 0xffffffff>
11-10 11:51:03.564 E/mono-rt ( 4924):   at System.Reflection.MonoMethod.Invoke (object,System.Reflection.BindingFlags,System.Reflection.Binder,object[],System.Globalization.CultureInfo) <IL 0x0004a, 0x0016f>
11-10 11:51:03.564 E/mono-rt ( 4924):   at System.Reflection.MethodBase.Invoke (object,object[]) <IL 0x00006, 0x0004b>
11-10 11:51:03.564 E/mono-rt ( 4924):   at Xamarin.Forms.BindingExpression.ApplyCore (object,Xamarin.Forms.BindableObject,Xamarin.Forms.BindableProperty,bool) <IL 0x002f4, 0x00fd3>
11-10 11:51:03.564 E/mono-rt ( 4924):   at Xamarin.Forms.BindingExpression.Apply (bool) <IL 0x00041, 0x000f3>
11-10 11:51:03.564 E/mono-rt ( 4924):   at Xamarin.Forms.Binding.Apply (bool) <IL 0x00027, 0x000db>
11-10 11:51:03.564 E/mono-rt ( 4924):   at Xamarin.Forms.BindableObject.SetValueActual (Xamarin.Forms.BindableProperty,object,bool,bool,bool) <IL 0x00090, 0x00295>
11-10 11:51:03.564 E/mono-rt ( 4924):   at Xamarin.Forms.BindableObject.SetValueCore (Xamarin.Forms.BindableProperty,object,bool,bool,bool) <IL 0x00213, 0x007b7>
11-10 11:51:03.564 E/mono-rt ( 4924):   at Xamarin.Forms.Platform.Android.EntryRenderer.Android.Text.ITextWatcher.OnTextChanged (Java.Lang.ICharSequence,int,int,int) <IL 0x00014, 0x00087>
11-10 11:51:03.564 E/mono-rt ( 4924):   at Android.Text.ITextWatcherInvoker.n_OnTextChanged_Ljava_lang_CharSequence_III (intptr,intptr,intptr,int,int,int) [0x00011] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.18-series/3b7ef0a7/source/monodroid/src/Mono.Android/platforms/android-18/src/generated/Android.Text.ITextWatcher.cs:149
11-10 11:51:03.564 E/mono-rt ( 4924):   at (wrapper dynamic-method) object.369fe85e-8bc0-4aec-88da-b1540ec93f9c (intptr,intptr,intptr,int,int,int) <IL 0x00029, 0x0003f>
11-10 11:51:03.564 E/mono-rt ( 4924):   at (wrapper native-to-managed) object.369fe85e-8bc0-4aec-88da-b1540ec93f9c (intptr,intptr,intptr,int,int,int) <IL 0x00028, 0xffffffff>
11-10 11:51:03.564 E/mono-rt ( 4924): 
11-10 11:51:03.564 E/mono-rt ( 4924): =================================================================
11-10 11:51:03.564 E/mono-rt ( 4924): Got a SIGSEGV while executing native code. This usually indicates
11-10 11:51:03.564 E/mono-rt ( 4924): a fatal error in the mono runtime or one of the native libraries 
11-10 11:51:03.564 E/mono-rt ( 4924): used by your application.
11-10 11:51:03.564 E/mono-rt ( 4924): =================================================================
11-10 11:51:03.564 E/mono-rt ( 4924): 
11-10 11:51:03.564 F/libc    ( 4924): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 4924 (r.nimbus.mobile)
The program 'Mono' has exited with code 0 (0x0).

As it appears to me to much events are fired which causes event stack to overflow.

Entry is working fine when bound to non Breeze property. It is also working fine when bound to detached entity.

After digging into Breeze EntityAspect.cs code I found out that all comes to this function:

internal void OnPropertyChanged(PropertyChangedEventArgs pcArgs)
    {
      if (this.IsDetached || !this.EntityGroup.ChangeNotificationEnabled)
        return;
      pcArgs = pcArgs ?? EntityAspect.AllPropertiesChangedEventArgs;
      this.QueueEvent((Action) (() =>
      {
        this.OnPropertyChangedCore(pcArgs);
        this.OnEntityChangedCore(EntityAction.PropertyChange, (EventArgs) pcArgs);
      }));
    }

So I disabled raising events in Breeze using:

this.EntityManager.ChangeNotificationEnabled = false;

It appears that this solves our issue with entry binding, but we are not sure if this opens door for other issues.

What are consequences of this approach?

Are these EntityPropertyChanged and PropertyChanged events used by Breeze code or intended only for our code to attach on them?

Or do you see some other approach for this issue?

UPDATE: Consequences are: if we have more that one element on UI bound to the same property and if we update that property on one place, change is not visible on other places.

Example: Select element from ListView and bound selected element to some entry fields (outside the ListView). When we update element through that entry fields, change is not visible on ListView (as ListView isn't notified).

With Breeze PropertyChanged mechanism enabled (EntityPropertyChanged and ForceEntityPropertyChanged) this would work out of the box, but as I mentioned above there is problem with the application crash.

We ended up implementing OnPropertyChanged and RaisePropertyChanged methods in our base entity (the one that inherits from Breeze BaseEntity). This technique is similar to MVVMLight implementation of ObservableObject.

This code works fine (without application crash):

public bool IsImportant
{
    get { return this.GetValue<bool>(); }
    set
    {
        this.SetValue(value); 
        this.OnPropertyChanged();
    }
}

Also we are able to call RaisePropertyChanged whenever it is needed:

this.SelectedNote.RaisePropertyChanged("IsImportant");
2

2 Answers

0
votes

I'm guessing there's a way to modify the binding to fire only after the user has finished editing the text, instead of every character change. Would that be sufficient for what you're trying to accomplish with your application? In WPF/Silverlight XAML there exists a property called UpdateSourceTrigger on the binding which you can set to dictate at which point changes are pushed. I'm in the process of contacting Xamarin to find out if they have an equivalent property.

0
votes

Didn't test, but you can disable property notification on the EntityManager, so you can toggle this property on demand.