summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.WinRT
diff options
context:
space:
mode:
authorStephane Delcroix <stephane@delcroix.org>2016-09-08 20:39:05 +0200
committerJason Smith <jason.smith@xamarin.com>2016-09-08 11:39:05 -0700
commit85426c5d9495eb1d55b3128bf97e50c68a73b53f (patch)
tree2f81e5868ce61eb90d15c6c51a354603b8395627 /Xamarin.Forms.Platform.WinRT
parent11326e1c182b3ff5c3d82c6ef7d09c193bc19891 (diff)
downloadxamarin-forms-85426c5d9495eb1d55b3128bf97e50c68a73b53f.tar.gz
xamarin-forms-85426c5d9495eb1d55b3128bf97e50c68a73b53f.tar.bz2
xamarin-forms-85426c5d9495eb1d55b3128bf97e50c68a73b53f.zip
Native Bindings (#278)
* [C, I, A, W] Support Native Bindings * fix tabs
Diffstat (limited to 'Xamarin.Forms.Platform.WinRT')
-rw-r--r--Xamarin.Forms.Platform.WinRT/FrameworkElementExtensions.cs16
-rw-r--r--Xamarin.Forms.Platform.WinRT/NativeBindingExtensions.cs58
-rw-r--r--Xamarin.Forms.Platform.WinRT/NativeEventWrapper.cs45
-rw-r--r--Xamarin.Forms.Platform.WinRT/NativePropertyListener.cs47
-rw-r--r--Xamarin.Forms.Platform.WinRT/NativeViewWrapper.cs8
-rw-r--r--Xamarin.Forms.Platform.WinRT/Xamarin.Forms.Platform.WinRT.csproj5
6 files changed, 178 insertions, 1 deletions
diff --git a/Xamarin.Forms.Platform.WinRT/FrameworkElementExtensions.cs b/Xamarin.Forms.Platform.WinRT/FrameworkElementExtensions.cs
index eb040e02..f94f3d62 100644
--- a/Xamarin.Forms.Platform.WinRT/FrameworkElementExtensions.cs
+++ b/Xamarin.Forms.Platform.WinRT/FrameworkElementExtensions.cs
@@ -128,5 +128,21 @@ namespace Xamarin.Forms.Platform.WinRT
return foregroundProperty;
}
+
+ internal static IEnumerable<T> GetChildren<T>(this DependencyObject parent) where T : DependencyObject
+ {
+ int myChildrenCount = VisualTreeHelper.GetChildrenCount(parent);
+ for (int i = 0; i < myChildrenCount; i++)
+ {
+ var child = VisualTreeHelper.GetChild(parent, i);
+ if (child is T)
+ yield return child as T;
+ else
+ {
+ foreach (var subChild in child.GetChildren<T>())
+ yield return subChild;
+ }
+ }
+ }
}
} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/NativeBindingExtensions.cs b/Xamarin.Forms.Platform.WinRT/NativeBindingExtensions.cs
new file mode 100644
index 00000000..cc88c87e
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/NativeBindingExtensions.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using Windows.UI.Xaml;
+using static System.String;
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public static class NativeBindingExtensions
+ {
+ public static void SetBinding(this FrameworkElement view, string propertyName, BindingBase bindingBase, string updateSourceEventName = null)
+ {
+ var binding = bindingBase as Binding;
+ updateSourceEventName = updateSourceEventName ?? binding?.UpdateSourceEventName;
+
+ if (IsNullOrEmpty(updateSourceEventName))
+ {
+ NativePropertyListener nativePropertyListener = null;
+ if (bindingBase.Mode == BindingMode.TwoWay)
+ nativePropertyListener = new NativePropertyListener(view, propertyName);
+
+ NativeBindingHelpers.SetBinding(view, propertyName, bindingBase, nativePropertyListener as INotifyPropertyChanged);
+ return;
+ }
+
+ NativeEventWrapper eventE = null;
+ if (binding.Mode == BindingMode.TwoWay && !(view is INotifyPropertyChanged))
+ eventE = new NativeEventWrapper(view, propertyName, updateSourceEventName);
+
+ NativeBindingHelpers.SetBinding(view, propertyName, binding, eventE);
+ }
+
+ public static void SetBinding(this FrameworkElement view, BindableProperty targetProperty, BindingBase binding)
+ {
+ NativeBindingHelpers.SetBinding(view, targetProperty, binding);
+ }
+
+ public static void SetValue(this FrameworkElement target, BindableProperty targetProperty, object value)
+ {
+ NativeBindingHelpers.SetValue(target, targetProperty, value);
+ }
+
+ public static void SetBindingContext(this FrameworkElement target, object bindingContext, Func<FrameworkElement, IEnumerable<FrameworkElement>> getChildren = null)
+ {
+ NativeBindingHelpers.SetBindingContext(target, bindingContext, getChildren);
+ }
+
+ internal static void TransferbindablePropertiesToWrapper(this FrameworkElement target, View wrapper)
+ {
+ NativeBindingHelpers.TransferBindablePropertiesToWrapper(target, wrapper);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/NativeEventWrapper.cs b/Xamarin.Forms.Platform.WinRT/NativeEventWrapper.cs
new file mode 100644
index 00000000..e28ca0eb
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/NativeEventWrapper.cs
@@ -0,0 +1,45 @@
+using System;
+using System.ComponentModel;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.InteropServices.WindowsRuntime;
+using Windows.UI.Xaml;
+
+#if WINDOWS_UWP
+namespace Xamarin.Forms.Platform.UWP
+#else
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ class NativeEventWrapper : INotifyPropertyChanged
+ {
+ static string TargetProperty { get; set; }
+ static readonly MethodInfo s_handlerinfo = typeof(NativeEventWrapper).GetRuntimeMethods().Single(mi => mi.Name == nameof(OnPropertyChanged) && mi.IsPublic == false);
+
+ public NativeEventWrapper(object target, string targetProperty, string updateSourceEventName)
+ {
+ TargetProperty = targetProperty;
+ try {
+ var updateSourceEvent = target.GetType().GetRuntimeEvent(updateSourceEventName);
+ MethodInfo addMethod = updateSourceEvent.AddMethod;
+ MethodInfo removeMethod = updateSourceEvent.RemoveMethod;
+ ParameterInfo[] addParameters = addMethod.GetParameters();
+ Type delegateType = addParameters[0].ParameterType;
+ var handlerDelegate = s_handlerinfo.CreateDelegate(delegateType, this);
+ Func<object, EventRegistrationToken> add = a => (EventRegistrationToken)addMethod.Invoke(target, new object[] { handlerDelegate });
+ Action<EventRegistrationToken> remove = t => removeMethod.Invoke(target, new object[] { t });
+ WindowsRuntimeMarshal.AddEventHandler(add, remove, s_handlerinfo);
+ }
+ catch (Exception) {
+ Log.Warning(nameof(NativeEventWrapper), "Can not attach NativeEventWrapper.");
+ }
+ }
+
+ void OnPropertyChanged(object sender, RoutedEventArgs e)
+ {
+ PropertyChanged?.Invoke(sender, new PropertyChangedEventArgs(TargetProperty));
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+ }
+}
diff --git a/Xamarin.Forms.Platform.WinRT/NativePropertyListener.cs b/Xamarin.Forms.Platform.WinRT/NativePropertyListener.cs
new file mode 100644
index 00000000..5a1b294c
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/NativePropertyListener.cs
@@ -0,0 +1,47 @@
+using System;
+using System.ComponentModel;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Data;
+
+#if WINDOWS_UWP
+namespace Xamarin.Forms.Platform.UWP
+#else
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ class NativePropertyListener : DependencyObject, INotifyPropertyChanged
+ {
+ readonly DependencyObject _target;
+ readonly string _targetProperty;
+
+ public static readonly DependencyProperty TargetPropertyValueProperty = DependencyProperty.Register(nameof(TargetPropertyValue), typeof(object), typeof(NativePropertyListener), new PropertyMetadata(null, OnNativePropertyChanged));
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ public NativePropertyListener(DependencyObject target, string propertyName)
+ {
+ _target = target;
+ _targetProperty = propertyName;
+ BindingOperations.SetBinding(this, TargetPropertyValueProperty, new Windows.UI.Xaml.Data.Binding() { Source = _target, Path = new PropertyPath(_targetProperty), Mode = Windows.UI.Xaml.Data.BindingMode.OneWay });
+ }
+
+ public void Dispose()
+ {
+ ClearValue(TargetPropertyValueProperty);
+ }
+
+ public object TargetPropertyValue
+ {
+ get
+ {
+ return GetValue(TargetPropertyValueProperty);
+ }
+ }
+
+ static void OnNativePropertyChanged(object sender, DependencyPropertyChangedEventArgs args)
+ {
+ NativePropertyListener source = (NativePropertyListener)sender;
+ source?.PropertyChanged?.Invoke(source._target, new PropertyChangedEventArgs(source._targetProperty));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/NativeViewWrapper.cs b/Xamarin.Forms.Platform.WinRT/NativeViewWrapper.cs
index 824f0eed..22cca62e 100644
--- a/Xamarin.Forms.Platform.WinRT/NativeViewWrapper.cs
+++ b/Xamarin.Forms.Platform.WinRT/NativeViewWrapper.cs
@@ -1,4 +1,5 @@
using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
#if WINDOWS_UWP
@@ -17,6 +18,7 @@ namespace Xamarin.Forms.Platform.WinRT
ArrangeOverrideDelegate = arrangeOverrideDelegate;
MeasureOverrideDelegate = measureOverrideDelegate;
NativeElement = nativeElement;
+ nativeElement.TransferbindablePropertiesToWrapper(this);
}
public ArrangeOverrideDelegate ArrangeOverrideDelegate { get; set; }
@@ -26,5 +28,11 @@ namespace Xamarin.Forms.Platform.WinRT
public MeasureOverrideDelegate MeasureOverrideDelegate { get; set; }
public FrameworkElement NativeElement { get; }
+
+ protected override void OnBindingContextChanged()
+ {
+ NativeElement.SetBindingContext(BindingContext, nv => nv.GetChildren<FrameworkElement>());
+ base.OnBindingContextChanged();
+ }
}
} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/Xamarin.Forms.Platform.WinRT.csproj b/Xamarin.Forms.Platform.WinRT/Xamarin.Forms.Platform.WinRT.csproj
index fd73aae0..ea456c00 100644
--- a/Xamarin.Forms.Platform.WinRT/Xamarin.Forms.Platform.WinRT.csproj
+++ b/Xamarin.Forms.Platform.WinRT/Xamarin.Forms.Platform.WinRT.csproj
@@ -69,7 +69,10 @@
<Compile Include="PlatformConfigurationExtensions.cs" />
</ItemGroup>
<ItemGroup Condition=" '$(OS)' != 'Unix' ">
- <Compile Include="BrushHelpers.cs" />
+ <Compile Include="BrushHelpers.cs" />
+ <Compile Include="NativeBindingExtensions.cs" />
+ <Compile Include="NativeEventWrapper.cs" />
+ <Compile Include="NativePropertyListener.cs" />
<Compile Include="NativeViewWrapper.cs" />
<Compile Include="NativeViewWrapperRenderer.cs" />
<Compile Include="ViewExtensions.cs" />