[Core] Can bind properties in BindableObjects added to static resources in XAML ...
authorSamantha Houts <samantha@teamredwall.com>
Tue, 12 Apr 2016 18:35:01 +0000 (11:35 -0700)
committerJason Smith <jason.smith@xamarin.com>
Tue, 12 Apr 2016 18:35:00 +0000 (11:35 -0700)
Resources that are `BindableObject`s will inherit the `Parent`'s `BindingContext` unless they are `Element`s that have non-null `Parent`s.

Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla23942.xaml [new file with mode: 0644]
Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla23942.xaml.cs [new file with mode: 0644]
Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems
Xamarin.Forms.Core/BindableObject.cs
Xamarin.Forms.Core/Element.cs

diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla23942.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla23942.xaml
new file mode 100644 (file)
index 0000000..d207cd2
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<local:TestContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+                        xmlns:test="clr-namespace:Xamarin.Forms.Controls.Issues"
+                        xmlns:local="clr-namespace:Xamarin.Forms.Controls"
+             x:Class="Xamarin.Forms.Controls.Issues.Bugzilla23942">
+
+       <local:TestContentPage.Resources>
+               <ResourceDictionary>
+                       <test:Bugzilla23942Options x:Key="opts" 
+                                                                               Text="{Binding DoesItWork}" />
+               </ResourceDictionary>
+       </local:TestContentPage.Resources>
+
+       <local:TestContentPage.Content>
+               <StackLayout>
+                       <test:Bugzilla23942Label x:Name="label"  Options="{DynamicResource opts}" />
+               </StackLayout>
+       </local:TestContentPage.Content>
+
+</local:TestContentPage>
\ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla23942.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla23942.xaml.cs
new file mode 100644 (file)
index 0000000..efa7894
--- /dev/null
@@ -0,0 +1,111 @@
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls.Issues
+{
+       [Preserve(AllMembers = true)]
+       [Issue(IssueTracker.Bugzilla, 23942, "Cannot bind properties in BindableObjects added to static resources in XAML", PlatformAffected.All)]
+       public partial class Bugzilla23942 : TestContentPage
+       {
+               [Preserve(AllMembers = true)]
+               public class TestViewModel : ViewModelBase
+               {
+                       string _doesItWork;
+                       public string DoesItWork
+                       {
+                               get
+                               {
+                                       return _doesItWork;
+                               }
+                               set
+                               {
+                                       _doesItWork = value;
+                                       OnPropertyChanged();
+                               }
+                       }
+               }
+
+#if APP
+               public Bugzilla23942()
+               {
+                       InitializeComponent();
+               }
+#endif
+
+               private void InitializeView()
+               {
+                       TestViewModel vm = new TestViewModel() { DoesItWork = "initial binding works" };
+                       BindingContext = vm;
+                       vm.DoesItWork = "success";
+               }
+
+               protected override void Init()
+               {
+                       InitializeView();
+               }
+
+               protected override void OnAppearing()
+               {
+                       base.OnAppearing();
+                       var lbl = this.FindByName<Bugzilla23942Label>("label");
+                       lbl.Text = lbl.Options.Text;
+               }
+
+#if UITEST
+               [Test]
+               public void Bugzilla23942Test()
+               {
+                       RunningApp.WaitForElement(q => q.Marked("success"));
+               }
+#endif
+       }
+
+       [Preserve(AllMembers = true)]
+       public class Bugzilla23942Options : BindableObject
+       {
+               public static readonly BindableProperty TextProperty =
+                       BindableProperty.Create(propertyName: nameof(Text),
+                                                                       returnType: typeof(string),
+                                                                       declaringType: typeof(Bugzilla23942Options),
+                                                                       defaultValue: default(string));
+
+               public string Text
+               {
+                       get
+                       {
+                               return (string)GetValue(TextProperty);
+                       }
+                       set
+                       {
+                               SetValue(TextProperty, value);
+                       }
+               }
+       }
+
+       [Preserve(AllMembers = true)]
+       public class Bugzilla23942Label : Label
+       {
+               public static readonly BindableProperty OptionsProperty =
+                       BindableProperty.Create(propertyName: nameof(Options),
+                                                                       returnType: typeof(Bugzilla23942Options),
+                                                                       declaringType: typeof(Bugzilla23942Label),
+                                                                       defaultValue: default(Bugzilla23942Options));
+
+               public Bugzilla23942Options Options
+               {
+                       get
+                       {
+                               return (Bugzilla23942Options)GetValue(OptionsProperty);
+                       }
+                       set
+                       {
+                               SetValue(OptionsProperty, value);
+                       }
+               }
+       }
+}
index ca43a27..6a1e0b9 100644 (file)
@@ -18,6 +18,9 @@
       <DependentUpon>Bugzilla22229.xaml</DependentUpon>
     </Compile>
     <Compile Include="$(MSBuildThisFileDirectory)Bugzilla22401.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Bugzilla23942.xaml.cs">
+      <DependentUpon>Bugzilla23942.xaml</DependentUpon>
+    </Compile>
     <Compile Include="$(MSBuildThisFileDirectory)Bugzilla24769.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Bugzilla25234.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Bugzilla25662.cs" />
     </EmbeddedResource>
   </ItemGroup>
   <ItemGroup>
+    <EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla23942.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
     <EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla39636.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
index 683d390..f348200 100644 (file)
@@ -360,7 +360,7 @@ namespace Xamarin.Forms
 
                        if (fromStyle)
                                context.Attributes |= BindableContextAttributes.IsSetFromStyle;
-                       // else ommitted on purpose
+                       // else omitted on purpose
 
                        bool currentlyApplying = _applying;
 
index a85bb3f..b631273 100644 (file)
@@ -17,6 +17,8 @@ namespace Xamarin.Forms
 
                string _automationId;
 
+               IList<BindableObject> _bindableResources;
+
                List<Action<object, ResourcesChangedEventArgs>> _changeHandlers;
 
                List<KeyValuePair<string, BindableProperty>> _dynamicResources;
@@ -321,6 +323,12 @@ namespace Xamarin.Forms
                                SetChildInheritedBindingContext(child, bc);
                        }
 
+                       if (_bindableResources != null)
+                               foreach (BindableObject item in _bindableResources)
+                               {
+                                       SetInheritedBindingContext(item, BindingContext);
+                               }
+
                        base.OnBindingContextChanged();
                }
 
@@ -420,6 +428,8 @@ namespace Xamarin.Forms
                                        handler(this, new ResourcesChangedEventArgs(values));
                        if (_dynamicResources == null)
                                return;
+                       if (_bindableResources == null)
+                               _bindableResources = new List<BindableObject>();
                        foreach (KeyValuePair<string, object> value in values)
                        {
                                List<BindableProperty> changedResources = null;
@@ -434,6 +444,14 @@ namespace Xamarin.Forms
                                        continue;
                                foreach (BindableProperty changedResource in changedResources)
                                        OnResourceChanged(changedResource, value.Value);
+
+                               var bindableObject = value.Value as BindableObject;
+                               if (bindableObject != null && (bindableObject as Element)?.Parent == null)
+                               {
+                                       if (!_bindableResources.Contains(bindableObject))
+                                               _bindableResources.Add(bindableObject);
+                                       SetInheritedBindingContext(bindableObject, BindingContext);
+                               }
                        }
                }