From 0dc34bd1741cc32fadecd0ad3f073b75f5ce4f07 Mon Sep 17 00:00:00 2001 From: David Oliver Date: Thu, 1 Oct 2020 06:29:38 -0400 Subject: [PATCH] fix: Don't propagate DataContext via Border.Child Restore the Uno 2.x behaviour whereby Border.ChildProperty doesn't propagate inherited values (including DataContext) to the property value. The inheritance is handled by the visual tree in the normal case (since Child is always a view). This restores the ability for the framework to call SetParent() to simulate a different inheritance hierarchy than the actual visual tree configuration, eg for AppBarButton using the native style. --- ...ge_With_AppBarButton_Visibility_Bound.xaml | 22 +++++++++ ...With_AppBarButton_Visibility_Bound.xaml.cs | 30 ++++++++++++ .../Given_AppBarButton.cs | 46 +++++++++++++++++++ .../Windows_UI_Xaml_Controls/Given_Border.cs | 41 +++++++++++++++++ src/Uno.UI/UI/Xaml/Controls/Border/Border.cs | 4 ++ 5 files changed, 143 insertions(+) create mode 100644 src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/FramePages/Page_With_AppBarButton_Visibility_Bound.xaml create mode 100644 src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/FramePages/Page_With_AppBarButton_Visibility_Bound.xaml.cs create mode 100644 src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_AppBarButton.cs create mode 100644 src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_Border.cs diff --git a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/FramePages/Page_With_AppBarButton_Visibility_Bound.xaml b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/FramePages/Page_With_AppBarButton_Visibility_Bound.xaml new file mode 100644 index 000000000000..1552f0412110 --- /dev/null +++ b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/FramePages/Page_With_AppBarButton_Visibility_Bound.xaml @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/FramePages/Page_With_AppBarButton_Visibility_Bound.xaml.cs b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/FramePages/Page_With_AppBarButton_Visibility_Bound.xaml.cs new file mode 100644 index 000000000000..c3a395d0eb17 --- /dev/null +++ b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/FramePages/Page_With_AppBarButton_Visibility_Bound.xaml.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Navigation; + +// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +namespace Uno.UI.RuntimeTests.Tests.Windows_UI_Xaml_Controls.FramePages +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class Page_With_AppBarButton_Visibility_Bound : Page + { + public Page_With_AppBarButton_Visibility_Bound() + { + this.InitializeComponent(); + } + } +} diff --git a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_AppBarButton.cs b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_AppBarButton.cs new file mode 100644 index 000000000000..9afbea207bab --- /dev/null +++ b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_AppBarButton.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Uno.UI.RuntimeTests.Helpers; +using Uno.UI.RuntimeTests.Tests.Windows_UI_Xaml_Controls.FramePages; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using static Private.Infrastructure.TestServices; + +namespace Uno.UI.RuntimeTests.Tests.Windows_UI_Xaml_Controls +{ + [TestClass] + [RunsOnUIThread] + public class Given_AppBarButton + { + [TestMethod] + public async Task Check_DataContext_Propagation() + { + using (StyleHelper.UseNativeFrameNavigation()) + { + var frame = new Frame(); + WindowHelper.WindowContent = frame; + await WindowHelper.WaitForIdle(); + frame.Navigate(typeof(Page_With_AppBarButton_Visibility_Bound)); + await WindowHelper.WaitForIdle(); + var page = frame.Content as Page_With_AppBarButton_Visibility_Bound; + Assert.IsNotNull(page); + page.DataContext = new MyContext(); + await WindowHelper.WaitForIdle(); + var tb = page.innerTextBlock; + Assert.IsNotNull(tb); + Assert.AreEqual("Archaeopteryx", tb.Text); + Assert.IsTrue(tb.ActualWidth > 0); + Assert.IsTrue(tb.ActualHeight > 0); + } + } + + private class MyContext + { + public Visibility ButtonVisibility => Visibility.Visible; + public string ButtonText => "Archaeopteryx"; + } + } +} diff --git a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_Border.cs b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_Border.cs new file mode 100644 index 000000000000..ef5710269bfd --- /dev/null +++ b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_Border.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Data; + +namespace Uno.UI.RuntimeTests.Tests.Windows_UI_Xaml_Controls +{ + [TestClass] + [RunsOnUIThread] + public class Given_Border + { + [TestMethod] + public void Check_DataContext_Propagation() + { + var tb = new TextBlock(); + tb.SetBinding(TextBlock.TextProperty, new Binding { Path = new PropertyPath("TestText") }); + var SUT = new Border + { + Child = tb + }; + + var root = new Grid + { + DataContext = new MyContext() + }; + + root.Children.Add(SUT); + + Assert.AreEqual("Vampire squid", tb.Text); + } + + private class MyContext + { + public string TestText => "Vampire squid"; + } + } +} diff --git a/src/Uno.UI/UI/Xaml/Controls/Border/Border.cs b/src/Uno.UI/UI/Xaml/Controls/Border/Border.cs index 1d2d6bf365cb..244e602c830f 100644 --- a/src/Uno.UI/UI/Xaml/Controls/Border/Border.cs +++ b/src/Uno.UI/UI/Xaml/Controls/Border/Border.cs @@ -75,6 +75,10 @@ public virtual UIElement Child typeof(Border), new FrameworkPropertyMetadata( null, + // Since this is a view, inheritance is handled through the visual tree, rather than via the property. We explicitly + // disable the property-based propagation here to support the case where the Parent property is overridden to simulate + // a different inheritance hierarchy, as is done for some controls with native styles. + FrameworkPropertyMetadataOptions.ValueDoesNotInheritDataContext, (s, e) => ((Border)s)?.OnChildChanged((UIElement)e.OldValue, (UIElement)e.NewValue) ) );