From 7d8ac1ec1ec80f8710a2c35bc3379759884148cd Mon Sep 17 00:00:00 2001 From: Laurent Bugnion Date: Sun, 18 Oct 2015 22:16:16 +0200 Subject: [PATCH] Fixing: Android: Binding UpdateSourceTrigger with LostFocus crashes the app Fixing: Binding UpdateSource/TargetTrigger set manually does not overwrite default value of event Adding missing System.Runtime and System.Threading.Tasks references to Android V5.2.1 --- .../Properties/AssemblyInfo.cs | 2 +- .../GalaSoft.MvvmLight (VS2013).sln | 4 +- .../Properties/AssemblyInfo.cs | 2 +- ...laSoft.MvvmLight.Platform (Android).csproj | 3 + .../Helpers/BindingGeneric.cs | 155 ++++++++++++++++-- .../Resources/Resource.Designer.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../GalaSoft.MvvmLight.Platform (iOS).csproj | 14 +- 8 files changed, 154 insertions(+), 30 deletions(-) diff --git a/GalaSoft.MvvmLight/GalaSoft.MvvmLight (PCL)/Properties/AssemblyInfo.cs b/GalaSoft.MvvmLight/GalaSoft.MvvmLight (PCL)/Properties/AssemblyInfo.cs index fff4a5f..cea1fe4 100644 --- a/GalaSoft.MvvmLight/GalaSoft.MvvmLight (PCL)/Properties/AssemblyInfo.cs +++ b/GalaSoft.MvvmLight/GalaSoft.MvvmLight (PCL)/Properties/AssemblyInfo.cs @@ -30,4 +30,4 @@ using System.Runtime.InteropServices; [assembly: CLSCompliant(true)] // BL0035 -[assembly: AssemblyVersion("5.2.0.*")] +[assembly: AssemblyVersion("5.2.1.*")] diff --git a/GalaSoft.MvvmLight/GalaSoft.MvvmLight (VS2013).sln b/GalaSoft.MvvmLight/GalaSoft.MvvmLight (VS2013).sln index 49806e0..aa9b492 100644 --- a/GalaSoft.MvvmLight/GalaSoft.MvvmLight (VS2013).sln +++ b/GalaSoft.MvvmLight/GalaSoft.MvvmLight (VS2013).sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 +# Visual Studio 14 +VisualStudioVersion = 14.0.23107.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GalaSoft.MvvmLight (PCL)", "GalaSoft.MvvmLight (PCL)\GalaSoft.MvvmLight (PCL).csproj", "{6A912701-3BA1-4975-ADBF-160CAF66B640}" EndProject diff --git a/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Extras (PCL)/Properties/AssemblyInfo.cs b/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Extras (PCL)/Properties/AssemblyInfo.cs index d0bf63d..dc1eeee 100644 --- a/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Extras (PCL)/Properties/AssemblyInfo.cs +++ b/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Extras (PCL)/Properties/AssemblyInfo.cs @@ -40,4 +40,4 @@ using System.Runtime.InteropServices; [assembly:NeutralResourcesLanguage("en-US")] // BL0035 -[assembly: AssemblyVersion("5.2.0.*")] +[assembly: AssemblyVersion("5.2.1.*")] diff --git a/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Platform (Android)/GalaSoft.MvvmLight.Platform (Android).csproj b/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Platform (Android)/GalaSoft.MvvmLight.Platform (Android).csproj index 0040ab0..b151ee5 100644 --- a/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Platform (Android)/GalaSoft.MvvmLight.Platform (Android).csproj +++ b/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Platform (Android)/GalaSoft.MvvmLight.Platform (Android).csproj @@ -15,6 +15,7 @@ Resources\Resource.Designer.cs Off True + v5.1 true @@ -42,6 +43,8 @@ + + diff --git a/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Platform (Android)/Helpers/BindingGeneric.cs b/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Platform (Android)/Helpers/BindingGeneric.cs index 940e70f..935b05f 100644 --- a/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Platform (Android)/Helpers/BindingGeneric.cs +++ b/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Platform (Android)/Helpers/BindingGeneric.cs @@ -20,8 +20,8 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Windows; - #if ANDROID +using Android.Views; using Android.Text; using Android.Widget; #endif @@ -44,10 +44,10 @@ namespace GalaSoft.MvvmLight.Helpers { private readonly SimpleConverter _converter = new SimpleConverter(); private readonly List _listeners = new List(); - private readonly Dictionary _sourceHandlers = new Dictionary(); + private readonly Dictionary _sourceHandlers = new Dictionary(); private readonly Expression> _sourcePropertyExpression; private readonly string _sourcePropertyName; - private readonly Dictionary _targetHandlers = new Dictionary(); + private readonly Dictionary _targetHandlers = new Dictionary(); private readonly Expression> _targetPropertyExpression; private readonly string _targetPropertyName; private WeakAction _onSourceUpdate; @@ -210,7 +210,8 @@ namespace GalaSoft.MvvmLight.Helpers _listeners.Clear(); - DetachHandlers(); + DetachSourceHandlers(); + DetachTargetHandlers(); } /// @@ -337,7 +338,27 @@ namespace GalaSoft.MvvmLight.Helpers // TODO Do we need weak events here? EventHandler handler = HandleSourceEvent; - _sourceHandlers.Add(eventName, handler); + + var defaultHandlerInfo = _sourceHandlers.Values.FirstOrDefault(i => i.IsDefault); + + if (defaultHandlerInfo != null) + { + DetachSourceHandlers(); + } + + var info = new DelegateInfo + { + Delegate = handler + }; + + if (_sourceHandlers.ContainsKey(eventName)) + { + _sourceHandlers[eventName] = info; + } + else + { + _sourceHandlers.Add(eventName, info); + } ev.AddEventHandler( _propertySource.Target, @@ -431,7 +452,13 @@ namespace GalaSoft.MvvmLight.Helpers switch (mode) { case UpdateTriggerMode.LostFocus: - return UpdateSourceTrigger("FocusChanged"); +#if ANDROID + return UpdateSourceTrigger("FocusChange"); +#else + throw new ArgumentException( + "UpdateTriggerMode.LostFocus is only supported in Android at this time", + "mode"); +#endif case UpdateTriggerMode.PropertyChanged: return CheckControlSource(); @@ -498,7 +525,27 @@ namespace GalaSoft.MvvmLight.Helpers // TODO Do we need weak events here? EventHandler handler = HandleSourceEvent; - _sourceHandlers.Add(eventName, handler); + + var defaultHandlerInfo = _sourceHandlers.Values.FirstOrDefault(i => i.IsDefault); + + if (defaultHandlerInfo != null) + { + DetachSourceHandlers(); + } + + var info = new DelegateInfo + { + Delegate = handler + }; + + if (_sourceHandlers.ContainsKey(eventName)) + { + _sourceHandlers[eventName] = info; + } + else + { + _sourceHandlers.Add(eventName, info); + } ev.AddEventHandler( _propertySource.Target, @@ -592,7 +639,13 @@ namespace GalaSoft.MvvmLight.Helpers switch (mode) { case UpdateTriggerMode.LostFocus: - return UpdateTargetTrigger("FocusChanged"); +#if ANDROID + return UpdateTargetTrigger("FocusChange"); +#else + throw new ArgumentException( + "UpdateTriggerMode.LostFocus is only supported in Android at this time", + "mode"); +#endif case UpdateTriggerMode.PropertyChanged: return CheckControlTarget(); @@ -662,7 +715,27 @@ namespace GalaSoft.MvvmLight.Helpers // TODO Do we need weak events here? EventHandler handler = HandleTargetEvent; - _targetHandlers.Add(eventName, handler); + + var defaultHandlerInfo = _targetHandlers.Values.FirstOrDefault(i => i.IsDefault); + + if (defaultHandlerInfo != null) + { + DetachTargetHandlers(); + } + + var info = new DelegateInfo + { + Delegate = handler + }; + + if (_targetHandlers.ContainsKey(eventName)) + { + _targetHandlers[eventName] = info; + } + else + { + _targetHandlers.Add(eventName, info); + } ev.AddEventHandler( _propertyTarget.Target, @@ -734,7 +807,27 @@ namespace GalaSoft.MvvmLight.Helpers // TODO Do we need weak events here? EventHandler handler = HandleTargetEvent; - _targetHandlers.Add(eventName, handler); + + var defaultHandlerInfo = _targetHandlers.Values.FirstOrDefault(i => i.IsDefault); + + if (defaultHandlerInfo != null) + { + DetachTargetHandlers(); + } + + var info = new DelegateInfo + { + Delegate = handler + }; + + if (_targetHandlers.ContainsKey(eventName)) + { + _targetHandlers[eventName] = info; + } + else + { + _targetHandlers.Add(eventName, info); + } ev.AddEventHandler( _propertyTarget.Target, @@ -1068,13 +1161,17 @@ namespace GalaSoft.MvvmLight.Helpers var textBox = _propertySource.Target as EditText; if (textBox != null) { - return UpdateSourceTrigger("TextChanged"); + var binding = UpdateSourceTrigger("TextChanged"); + binding._sourceHandlers["TextChanged"].IsDefault = true; + return binding; } var checkbox = _propertySource.Target as CompoundButton; if (checkbox != null) { - return UpdateSourceTrigger("CheckedChange"); + var binding = UpdateSourceTrigger("CheckedChange"); + binding._sourceHandlers["CheckedChange"].IsDefault = true; + return binding; } return this; @@ -1096,13 +1193,17 @@ namespace GalaSoft.MvvmLight.Helpers var textBox = _propertyTarget.Target as EditText; if (textBox != null) { - return UpdateTargetTrigger("TextChanged"); + var binding = UpdateTargetTrigger("TextChanged"); + binding._targetHandlers["TextChanged"].IsDefault = true; + return binding; } var checkbox = _propertyTarget.Target as CompoundButton; if (checkbox != null) { - return UpdateTargetTrigger("CheckedChange"); + var binding = UpdateTargetTrigger("CheckedChange"); + binding._targetHandlers["CheckedChange"].IsDefault = true; + return binding; } return this; @@ -1113,7 +1214,7 @@ namespace GalaSoft.MvvmLight.Helpers #endif } - private void DetachHandlers() + private void DetachSourceHandlers() { if (_propertySource == null || !_propertySource.IsAlive @@ -1131,7 +1232,19 @@ namespace GalaSoft.MvvmLight.Helpers return; } - ev.RemoveEventHandler(_propertySource.Target, _sourceHandlers[eventName]); + ev.RemoveEventHandler(_propertySource.Target, _sourceHandlers[eventName].Delegate); + } + + _sourceHandlers.Clear(); + } + + private void DetachTargetHandlers() + { + if (_propertySource == null + || !_propertySource.IsAlive + || _propertySource.Target == null) + { + return; } foreach (var eventName in _targetHandlers.Keys) @@ -1143,8 +1256,10 @@ namespace GalaSoft.MvvmLight.Helpers return; } - ev.RemoveEventHandler(_propertyTarget.Target, _targetHandlers[eventName]); + ev.RemoveEventHandler(_propertyTarget.Target, _targetHandlers[eventName].Delegate); } + + _targetHandlers.Clear(); } private TTarget GetSourceValue() @@ -1380,5 +1495,11 @@ namespace GalaSoft.MvvmLight.Helpers _convertBack = new WeakFunc(convertBack); } } + + private class DelegateInfo + { + public Delegate Delegate; + public bool IsDefault; + } } } \ No newline at end of file diff --git a/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Platform (Android)/Resources/Resource.Designer.cs b/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Platform (Android)/Resources/Resource.Designer.cs index a0fd544..2a6e7a6 100644 --- a/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Platform (Android)/Resources/Resource.Designer.cs +++ b/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Platform (Android)/Resources/Resource.Designer.cs @@ -2,7 +2,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.0 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. diff --git a/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Platform (NET45)/Properties/AssemblyInfo.cs b/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Platform (NET45)/Properties/AssemblyInfo.cs index 398c778..3558ea0 100644 --- a/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Platform (NET45)/Properties/AssemblyInfo.cs +++ b/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Platform (NET45)/Properties/AssemblyInfo.cs @@ -47,4 +47,4 @@ using System.Windows.Markup; [assembly:NeutralResourcesLanguage("en-US")] // BL0035 -[assembly: AssemblyVersion("5.2.0.*")] +[assembly: AssemblyVersion("5.2.1.*")] diff --git a/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Platform (iOS)/GalaSoft.MvvmLight.Platform (iOS).csproj b/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Platform (iOS)/GalaSoft.MvvmLight.Platform (iOS).csproj index 7f2238d..b5bf1d6 100644 --- a/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Platform (iOS)/GalaSoft.MvvmLight.Platform (iOS).csproj +++ b/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Platform (iOS)/GalaSoft.MvvmLight.Platform (iOS).csproj @@ -37,25 +37,25 @@ bin\iPhone\Release\GalaSoft.MvvmLight.Platform.XML - + Helpers\Binding.cs - + Helpers\BindingGeneric.cs - + Helpers\BindingMode.cs - + Helpers\Extensions.cs - + Helpers\IWeakEventListener.cs - + Helpers\PropertyChangedEventManager.cs - + Helpers\UpdateSourceTriggerMode.cs