[Shell] propagate css to logical child element (#6082) fixes #4683 fixes #5956
authorShane Neuville <shane94@hotmail.com>
Thu, 9 May 2019 21:17:30 +0000 (14:17 -0700)
committerRui Marinho <me@ruimarinho.net>
Thu, 9 May 2019 21:17:30 +0000 (14:17 -0700)
* create an actual logical child structure for page to use for propagation

* JustTheLogicalChildren

* only iterate over ActuallyLogicalChildren

* fix naming

* reuse ChildrenNotDrawnByThisElement

* testing

* fix unit test

Xamarin.Forms.Core.UnitTests/ShellTests.cs
Xamarin.Forms.Core/Element.cs
Xamarin.Forms.Core/Page.cs
Xamarin.Forms.Core/Shell/Shell.cs
Xamarin.Forms.Core/Shell/ShellSection.cs
Xamarin.Forms.Core/StyleSheets/StyleSheet.cs
Xamarin.Forms.Sandbox/App.StartHere.cs
Xamarin.Forms.Sandbox/MainPage.xaml
Xamarin.Forms.Sandbox/MainPage.xaml.cs
Xamarin.Forms.Sandbox/ShellPage.xaml
Xamarin.Forms.Sandbox/Styles.css [new file with mode: 0644]

index d1bf4b4..f0e6a95 100644 (file)
@@ -475,6 +475,50 @@ namespace Xamarin.Forms.Core.UnitTests
                }
 
 
+    [Test]
+               public async Task TitleViewLogicalChild()
+               {
+                       Shell shell = new Shell();
+                       ContentPage page = new ContentPage();
+                       shell.Items.Add(CreateShellItem(page));
+                       page.BindingContext = new { Text = "Binding" };
+
+                       // setup title view
+                       StackLayout layout = new StackLayout() { BackgroundColor = Color.White };
+                       Label label = new Label();
+                       label.SetBinding(Label.TextProperty, "Text");
+                       layout.Children.Add(label);
+                       Shell.SetTitleView(page, layout);
+
+
+                       Assert.True(page.ChildrenNotDrawnByThisElement.Contains(layout));
+               }
+
+
+               [Test]
+               public async Task FlyoutHeaderLogicalChild()
+               {
+                       Shell shell = new Shell();
+                       ContentPage page = new ContentPage();
+                       shell.Items.Add(CreateShellItem(page));
+
+                       // setup title view
+                       StackLayout layout = new StackLayout() { BackgroundColor = Color.White };
+                       Label label = new Label();
+                       label.SetBinding(Label.TextProperty, "Text");
+                       layout.Children.Add(label);
+
+
+                       shell.FlyoutHeader = null;
+                       shell.FlyoutHeader = layout;
+
+                       Assert.True(shell.ChildrenNotDrawnByThisElement.Contains(layout));
+                       shell.FlyoutHeader = null;
+
+                       Assert.False(shell.ChildrenNotDrawnByThisElement.Contains(layout));
+    }
+    
+    
                [Test]
                public async Task TabBarAutoCreation()
                {
index 19ad039..5149f35 100644 (file)
@@ -121,6 +121,20 @@ namespace Xamarin.Forms
                }
 
                internal virtual ReadOnlyCollection<Element> LogicalChildrenInternal => EmptyChildren;
+               internal IEnumerable<Element> AllChildren
+               {
+                       get
+                       {
+                               foreach (var child in LogicalChildrenInternal)
+                                       yield return child;
+
+                               foreach (var child in ChildrenNotDrawnByThisElement)
+                                       yield return child;
+                       }
+               }
+
+               internal virtual IEnumerable<Element> ChildrenNotDrawnByThisElement => EmptyChildren;
+
 
                [EditorBrowsable(EditorBrowsableState.Never)]
                public ReadOnlyCollection<Element> LogicalChildren => LogicalChildrenInternal;
@@ -337,10 +351,11 @@ namespace Xamarin.Forms
                protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
                {
                        base.OnPropertyChanged(propertyName);
-
-                       IPropertyPropagationController titleView = Shell.GetTitleView(this) ?? NavigationPage.GetTitleView(this);
-                       if(titleView != null)
-                               PropertyPropagationExtensions.PropagatePropertyChanged(propertyName, this, new[] { titleView });
+                       foreach(var logicalChildren in ChildrenNotDrawnByThisElement)
+                       {
+                               if(logicalChildren is IPropertyPropagationController controller)
+                                       PropertyPropagationExtensions.PropagatePropertyChanged(propertyName, this, new[] { logicalChildren });
+                       }
 
                        if (_effects == null || _effects.Count == 0)
                                return;
index 4873495..7ee9981 100644 (file)
@@ -144,6 +144,22 @@ namespace Xamarin.Forms
         [EditorBrowsable(EditorBrowsableState.Never)]
         public ObservableCollection<Element> InternalChildren { get; } = new ObservableCollection<Element>();
 
+               internal override IEnumerable<Element> ChildrenNotDrawnByThisElement
+               {
+                       get
+                       {
+                               var titleviewPart1TheShell = Shell.GetTitleView(this);
+                               var titleViewPart2TheNavBar = NavigationPage.GetTitleView(this);
+
+                               if (titleviewPart1TheShell != null)
+                                       yield return titleviewPart1TheShell;
+
+                               if (titleViewPart2TheNavBar != null)
+                                       yield return titleViewPart2TheNavBar;
+
+                       }
+               }
+
                internal override ReadOnlyCollection<Element> LogicalChildrenInternal => 
                        _logicalChildren ?? (_logicalChildren = new ReadOnlyCollection<Element>(InternalChildren));
 
index e7d4f85..1ed4814 100644 (file)
@@ -422,7 +422,7 @@ namespace Xamarin.Forms
                        {
                                await CurrentItem.CurrentItem.GoToAsync(navigationRequest, queryData, animate);
                        }
-                       
+
                        //if (Routing.CompareWithRegisteredRoutes(shellItemRoute))
                        //{
                        //      var shellItem = ShellItem.GetShellItemFromRouteName(shellItemRoute);
@@ -810,6 +810,16 @@ namespace Xamarin.Forms
                        }
                }
 
+               internal override IEnumerable<Element> ChildrenNotDrawnByThisElement
+               {
+                       get
+                       {
+                               if (FlyoutHeaderView != null)
+                                       yield return FlyoutHeaderView;
+                       }
+               }
+
+
                protected virtual void OnNavigated(ShellNavigatedEventArgs args)
                {
                        if (_accumulateNavigatedEvents)
@@ -1084,7 +1094,7 @@ namespace Xamarin.Forms
                {
                        readonly Shell _shell;
 
-                       NavigationProxy SectionProxy => _shell.CurrentItem.CurrentItem.NavigationProxy;                 
+                       NavigationProxy SectionProxy => _shell.CurrentItem.CurrentItem.NavigationProxy;
 
                        public NavigationImpl(Shell shell) => _shell = shell;
 
index c1fd9c4..25b4d4f 100644 (file)
@@ -324,6 +324,8 @@ namespace Xamarin.Forms
                        UpdateDisplayedPage();
                }
 
+               internal override IEnumerable<Element> ChildrenNotDrawnByThisElement => Items;
+
                protected virtual void OnInsertPageBefore(Page page, Page before)
                {
                        var index = _navStack.IndexOf(before);
index a932ef9..a9bd521 100644 (file)
@@ -97,7 +97,7 @@ namespace Xamarin.Forms.StyleSheets
                void Apply(Element styleable)
                {
                        ApplyCore(styleable);
-                       foreach (var child in styleable.LogicalChildrenInternal)
+                       foreach (var child in styleable.AllChildren)
                                ((IStyle)this).Apply(child);
                }
 
index baf862a..434ef74 100644 (file)
@@ -1,6 +1,8 @@
 using System;
 using System.Collections.Generic;
+using System.Reflection;
 using System.Text;
+using Xamarin.Forms.StyleSheets;
 
 namespace Xamarin.Forms.Sandbox
 {
@@ -9,9 +11,17 @@ namespace Xamarin.Forms.Sandbox
                // This code is called from the App Constructor so just initialize the main page of the application here
                void InitializeMainPage()
                {
-                       //MainPage = CreateStackLayoutPage(new[] { new Button() { Text = "text" } });
+
+
+                       this.Resources.Add(StyleSheet.FromAssemblyResource(
+                               IntrospectionExtensions.GetTypeInfo(typeof(App)).Assembly,
+                               "Xamarin.Forms.Sandbox.Styles.css"));
+
+                       //MainPage = CreateStackLayoutPage(new[] { new Button() {  Text = "text" } });
                        //MainPage.Visual = VisualMarker.Material;
-                       MainPage = new MainPage();
+                       MainPage = new ShellPage();
+
+               //      MainPage = new NavigationPage(new MainPage());
                }
        }
 }
index c610023..cd6639b 100644 (file)
@@ -1,12 +1,16 @@
-<?xml version="1.0" encoding="utf-8" ?>
+<?xml version="1.0" encoding="utf-8" ?>
 <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
              x:Class="Xamarin.Forms.Sandbox.MainPage"
              xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
              ios:Page.UseSafeArea="true">
-    <ContentPage.Content>
-        <StackLayout>
+
+    <NavigationPage.TitleView>
+        <Grid>
             <Button Text="I am a Button"  />
-        </StackLayout>
-    </ContentPage.Content>
+        </Grid>
+    </NavigationPage.TitleView>
+    <StackLayout>
+        <Button Text="I am a Button"  />
+    </StackLayout>
 </ContentPage>
\ No newline at end of file
index 84d196f..9e2a5cf 100644 (file)
@@ -11,7 +11,7 @@ namespace Xamarin.Forms.Sandbox
 {
        [XamlCompilation(XamlCompilationOptions.Compile)]
        public partial class MainPage : ContentPage
-       {
+    {
                public MainPage()
                {
                        InitializeComponent();
index e0cb676..d945d70 100644 (file)
@@ -1,9 +1,25 @@
 <?xml version="1.0" encoding="utf-8" ?>
 <Shell xmlns="http://xamarin.com/schemas/2014/forms"
              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
-             x:Class="Xamarin.Forms.Sandbox.ShellPage">
+             x:Class="Xamarin.Forms.Sandbox.ShellPage"
+             xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
+             ios:Page.UseSafeArea="true">
 
-    <ShellContent Title="test">
-        <ContentPage></ContentPage>
+    <Shell.FlyoutHeader>
+        <StackLayout>
+            <Button Text="I am a Button"  />
+        </StackLayout>
+    </Shell.FlyoutHeader>
+    <ShellContent>
+        <ContentPage>
+            <Shell.TitleView>
+                <StackLayout>
+                    <Button Text="I am a Button"  />
+                </StackLayout>
+            </Shell.TitleView>
+            <StackLayout>
+                <Button Text="I am a Button"  />
+            </StackLayout>
+        </ContentPage>
     </ShellContent>
 </Shell>
\ No newline at end of file
diff --git a/Xamarin.Forms.Sandbox/Styles.css b/Xamarin.Forms.Sandbox/Styles.css
new file mode 100644 (file)
index 0000000..9f5ac93
--- /dev/null
@@ -0,0 +1,4 @@
+button {
+    background-color:green;
+    color:#FFFFFF
+}