summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRui Marinho <me@ruimarinho.net>2016-09-30 19:48:22 +0100
committerRui Marinho <me@ruimarinho.net>2016-10-04 17:32:34 +0100
commit00a42778203539a0adf6037ba3f4dcad70c1869a (patch)
tree6771f05937b71c60e4902913e486ecb65e6fc452
parent65e06eef9051d5930d368f87c87d70044fc27f79 (diff)
downloadxamarin-forms-00a42778203539a0adf6037ba3f4dcad70c1869a.tar.gz
xamarin-forms-00a42778203539a0adf6037ba3f4dcad70c1869a.tar.bz2
xamarin-forms-00a42778203539a0adf6037ba3f4dcad70c1869a.zip
[iOS] Keep our native property listener around the same time we keep our proxy, check if we are KVO compliant before adding observer (#403)
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/AppDelegate.cs34
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/Xamarin.Forms.ControlGallery.iOS.csproj2
-rw-r--r--Xamarin.Forms.Controls/ControlGalleryPages/NativeBindingGalleryPage.cs15
-rw-r--r--Xamarin.Forms.Core/NativeBindingHelpers.cs9
-rw-r--r--Xamarin.Forms.Platform.iOS/Extensions/UIViewExtensions.cs26
-rw-r--r--Xamarin.Forms.Platform.iOS/NativeViewPropertyListener.cs4
6 files changed, 76 insertions, 14 deletions
diff --git a/Xamarin.Forms.ControlGallery.iOS/AppDelegate.cs b/Xamarin.Forms.ControlGallery.iOS/AppDelegate.cs
index 7614796a..5e1dcd79 100644
--- a/Xamarin.Forms.ControlGallery.iOS/AppDelegate.cs
+++ b/Xamarin.Forms.ControlGallery.iOS/AppDelegate.cs
@@ -312,6 +312,12 @@ namespace Xamarin.Forms.ControlGallery.iOS
uilabel.SetBinding("Text", new Binding("NativeLabel"));
uilabel.SetBinding(nameof(uilabel.TextColor), new Binding("NativeLabelColor", converter: nativeColorConverter));
+ var kvoSlider = new KVOUISlider();
+ kvoSlider.MaxValue = 100;
+ kvoSlider.MinValue = 0;
+ kvoSlider.SetBinding(nameof(kvoSlider.KVOValue), new Binding("Age", BindingMode.TwoWay));
+ sl?.Children.Add(kvoSlider);
+
var uiView = new UIView(new RectangleF(0, 0, width, heightCustomLabelView));
uiView.Add(uilabel);
sl?.Children.Add(uiView);
@@ -323,6 +329,34 @@ namespace Xamarin.Forms.ControlGallery.iOS
}
}
+ [Register("KVOUISlider")]
+ public class KVOUISlider : UISlider
+ {
+
+ public KVOUISlider()
+ {
+ ValueChanged += (s, e) => KVOValue = Value;
+ }
+
+ float _kVOValue;
+ [Export("kvovalue")]
+ public float KVOValue
+ {
+ get
+ {
+
+ return _kVOValue;
+ }
+ set
+ {
+
+ WillChangeValue(nameof(KVOValue).ToLower());
+ _kVOValue = Value = value;
+ DidChangeValue(nameof(KVOValue).ToLower());
+ }
+ }
+ }
+
public class ColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
diff --git a/Xamarin.Forms.ControlGallery.iOS/Xamarin.Forms.ControlGallery.iOS.csproj b/Xamarin.Forms.ControlGallery.iOS/Xamarin.Forms.ControlGallery.iOS.csproj
index fabf981a..aa9c7d91 100644
--- a/Xamarin.Forms.ControlGallery.iOS/Xamarin.Forms.ControlGallery.iOS.csproj
+++ b/Xamarin.Forms.ControlGallery.iOS/Xamarin.Forms.ControlGallery.iOS.csproj
@@ -270,4 +270,4 @@
<Visible>False</Visible>
</XamarinComponentReference>
</ItemGroup>
-</Project> \ No newline at end of file
+</Project>
diff --git a/Xamarin.Forms.Controls/ControlGalleryPages/NativeBindingGalleryPage.cs b/Xamarin.Forms.Controls/ControlGalleryPages/NativeBindingGalleryPage.cs
index 51d9b970..7373e0be 100644
--- a/Xamarin.Forms.Controls/ControlGalleryPages/NativeBindingGalleryPage.cs
+++ b/Xamarin.Forms.Controls/ControlGalleryPages/NativeBindingGalleryPage.cs
@@ -44,13 +44,14 @@ namespace Xamarin.Forms.Controls
var label = new Label();
label.SetBinding(Label.TextProperty, "FormsLabel");
+ var labelAge = new Label();
+ labelAge.SetBinding(Label.TextProperty, nameof(vm.Age));
Layout.Children.Add(buttonNav);
-
Layout.Children.Add(label);
-
Layout.Children.Add(boxView);
Layout.Children.Add(button);
+ Layout.Children.Add(labelAge);
BindingContext = ViewModel = vm; ;
@@ -66,35 +67,35 @@ namespace Xamarin.Forms.Controls
public string FormsLabel
{
get { return _formsLabel; }
- set { _formsLabel = value; OnPropertyChanged(); }
+ set { if (_formsLabel == value) return; _formsLabel = value; OnPropertyChanged(); }
}
string _nativeLabel;
public string NativeLabel
{
get { return _nativeLabel; }
- set { _nativeLabel = value; OnPropertyChanged(); }
+ set { if (_nativeLabel == value) return; _nativeLabel = value; OnPropertyChanged(); }
}
Color _nativeLabelColor;
public Color NativeLabelColor
{
get { return _nativeLabelColor; }
- set { _nativeLabelColor = value; OnPropertyChanged(); }
+ set { if (_nativeLabelColor == value) return; _nativeLabelColor = value; OnPropertyChanged(); }
}
int _age;
public int Age
{
get { return _age; }
- set { _age = value; OnPropertyChanged(); }
+ set { if (_age == value) return; _age = value; OnPropertyChanged(); }
}
bool _selected;
public bool Selected
{
get { return _selected; }
- set { _selected = value; OnPropertyChanged(); }
+ set { if (_selected == value) return; _selected = value; OnPropertyChanged(); }
}
}
diff --git a/Xamarin.Forms.Core/NativeBindingHelpers.cs b/Xamarin.Forms.Core/NativeBindingHelpers.cs
index 7e2db65b..e4cae7d9 100644
--- a/Xamarin.Forms.Core/NativeBindingHelpers.cs
+++ b/Xamarin.Forms.Core/NativeBindingHelpers.cs
@@ -43,8 +43,10 @@ namespace Xamarin.Forms
propertyChanged.PropertyChanged += (sender, e) => {
if (e.PropertyName != targetProperty)
return;
- SetValueFromNative<TNativeView>(sender as TNativeView, targetProperty, bindableProperty);
- };
+ SetValueFromNative<TNativeView>(sender as TNativeView, targetProperty, bindableProperty);
+ //we need to keep the listener around he same time we have the proxy
+ proxy.NativeINPCListener = propertyChanged;
+ };
if (binding != null && binding.Mode != BindingMode.OneWay)
SetValueFromNative(target, targetProperty, bindableProperty);
@@ -178,6 +180,7 @@ namespace Xamarin.Forms
public WeakReference<TNativeView> TargetReference { get; set; }
public IList<KeyValuePair<BindableProperty, BindingBase>> BindingsBackpack { get; } = new List<KeyValuePair<BindableProperty, BindingBase>>();
public IList<KeyValuePair<BindableProperty, object>> ValuesBackpack { get; } = new List<KeyValuePair<BindableProperty, object>>();
+ public INotifyPropertyChanged NativeINPCListener;
public BindableObjectProxy(TNativeView target)
{
@@ -193,4 +196,4 @@ namespace Xamarin.Forms
}
}
}
-} \ No newline at end of file
+}
diff --git a/Xamarin.Forms.Platform.iOS/Extensions/UIViewExtensions.cs b/Xamarin.Forms.Platform.iOS/Extensions/UIViewExtensions.cs
index eab88e81..4c3eed98 100644
--- a/Xamarin.Forms.Platform.iOS/Extensions/UIViewExtensions.cs
+++ b/Xamarin.Forms.Platform.iOS/Extensions/UIViewExtensions.cs
@@ -37,9 +37,31 @@ namespace Xamarin.Forms.Platform.iOS
}
NativeViewPropertyListener nativePropertyListener = null;
- if (bindingBase.Mode == BindingMode.TwoWay) {
+ if (bindingBase.Mode == BindingMode.TwoWay)
+ {
nativePropertyListener = new NativeViewPropertyListener(propertyName);
- view.AddObserver(nativePropertyListener, propertyName, 0, IntPtr.Zero);
+ try
+ {
+ //TODO: We need to figure a way to map the value back to the real objectiveC property.
+ //the X.IOS camelcase property name won't work
+ var key = new Foundation.NSString(propertyName.ToLower());
+ var valueKey = view.ValueForKey(key);
+ if (valueKey != null)
+ {
+ view.AddObserver(nativePropertyListener, key, Foundation.NSKeyValueObservingOptions.New, IntPtr.Zero);
+ }
+ }
+ catch (Foundation.MonoTouchException ex)
+ {
+ nativePropertyListener = null;
+ if (ex.Name == "NSUnknownKeyException")
+ {
+ System.Diagnostics.Debug.WriteLine("KVO not supported, try specify a UpdateSourceEventName instead.");
+ return;
+ }
+ throw ex;
+ }
+
}
NativeBindingHelpers.SetBinding(view, propertyName, bindingBase, nativePropertyListener);
diff --git a/Xamarin.Forms.Platform.iOS/NativeViewPropertyListener.cs b/Xamarin.Forms.Platform.iOS/NativeViewPropertyListener.cs
index 2d872af2..4e6601ef 100644
--- a/Xamarin.Forms.Platform.iOS/NativeViewPropertyListener.cs
+++ b/Xamarin.Forms.Platform.iOS/NativeViewPropertyListener.cs
@@ -17,8 +17,10 @@ namespace Xamarin.Forms.Platform.iOS
public override void ObserveValue(NSString keyPath, NSObject ofObject, NSDictionary change, IntPtr context)
{
- if (keyPath == TargetProperty)
+ if (keyPath.ToString().Equals(TargetProperty, StringComparison.InvariantCultureIgnoreCase))
PropertyChanged?.Invoke(ofObject, new PropertyChangedEventArgs(TargetProperty));
+ else
+ base.ObserveValue(keyPath, ofObject, change, context);
}
}
}