зеркало из https://github.com/DeGsoft/maui-linux.git
[Shell] Propagate Page bindings to TitleView and Shell Binding to Flyout (#5934) fixes #5650 fixes #5501
* propagate bindingcontext * - add exception message and fix poorly named xaml file * add ui test automation * - fix unit test to represent new code * - changed from ui test to unit test * - propagate visual, parent, bc to titleview * - style fixes
This commit is contained in:
Родитель
d63002c25f
Коммит
dbf4037a31
|
@ -581,6 +581,30 @@ namespace Xamarin.Forms.Controls
|
|||
#endif
|
||||
}
|
||||
|
||||
public ContentPage CreateContentPage()
|
||||
{
|
||||
ContentPage page = new ContentPage();
|
||||
ShellItem item = new ShellItem()
|
||||
{
|
||||
Items =
|
||||
{
|
||||
new ShellSection()
|
||||
{
|
||||
Items =
|
||||
{
|
||||
new ShellContent()
|
||||
{
|
||||
Content = page
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Items.Add(item);
|
||||
return page;
|
||||
|
||||
}
|
||||
#if UITEST
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
Routing.Route="shellcontent"
|
||||
Shell.SetPaddingInsets="true"
|
||||
Shell.TabBarIsVisible="false"
|
||||
x:Class="Xamarin.Forms.Controls.ShellContent">
|
||||
x:Class="Xamarin.Forms.Controls.ShellContentTest">
|
||||
<Page.ToolbarItems>
|
||||
<ToolbarItem Text="Search" Icon="bank.png" />
|
||||
</Page.ToolbarItems>
|
|
@ -13,7 +13,7 @@ namespace Xamarin.Forms.Controls
|
|||
[Preserve]
|
||||
[QueryProperty("Text", "welcome")]
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class ShellContent : ContentPage
|
||||
public partial class ShellContentTest : ContentPage
|
||||
{
|
||||
private class MySearchHandler : SearchHandler
|
||||
{
|
||||
|
@ -51,7 +51,7 @@ namespace Xamarin.Forms.Controls
|
|||
|
||||
private string _text;
|
||||
|
||||
public ShellContent()
|
||||
public ShellContentTest()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
|
@ -89,7 +89,7 @@ namespace Xamarin.Forms.Controls
|
|||
|
||||
private void InsertClicked(object sender, EventArgs e)
|
||||
{
|
||||
Navigation.InsertPageBefore(new ShellContent(), this);
|
||||
Navigation.InsertPageBefore(new ShellContentTest(), this);
|
||||
}
|
||||
|
||||
private void ToggleClicked(object sender, EventArgs e)
|
||||
|
@ -122,7 +122,7 @@ namespace Xamarin.Forms.Controls
|
|||
|
||||
private async void PushClicked(object sender, EventArgs e)
|
||||
{
|
||||
await Navigation.PushAsync(new ShellContent()
|
||||
await Navigation.PushAsync(new ShellContentTest()
|
||||
{
|
||||
Text = Text + "1"
|
||||
});
|
|
@ -50,6 +50,9 @@
|
|||
<Compile Update="GalleryPages\VisualStateManagerGalleries\OnPlatformExample.xaml.cs">
|
||||
<DependentUpon>OnPlatformExample.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="ShellContentTest.xaml.cs">
|
||||
<DependentUpon>ShellContentTest.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<EmbeddedResource Update="GalleryPages\BindableLayoutGalleryPage.xaml">
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
</EmbeddedResource>
|
||||
|
|
|
@ -303,6 +303,9 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
|
||||
var label = new Label();
|
||||
|
||||
var viewModel = new Object();
|
||||
shell.BindingContext = viewModel;
|
||||
|
||||
shell.FlyoutHeader = label;
|
||||
|
||||
Assert.AreEqual(((IShellController)shell).FlyoutHeader, label);
|
||||
|
@ -315,7 +318,7 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
});
|
||||
|
||||
Assert.AreEqual(((IShellController)shell).FlyoutHeader, label2);
|
||||
Assert.AreEqual(((IShellController)shell).FlyoutHeader.BindingContext, label);
|
||||
Assert.AreEqual(((IShellController)shell).FlyoutHeader.BindingContext, viewModel);
|
||||
|
||||
shell.FlyoutHeaderTemplate = null;
|
||||
|
||||
|
@ -370,5 +373,110 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
shell.GoToAsync("//rootlevelcontent1");
|
||||
Assert.AreEqual(shell.CurrentItem, item1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TitleViewBindingContext()
|
||||
{
|
||||
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.AreEqual("Binding", label.Text);
|
||||
page.BindingContext = new { Text = "Binding Changed" };
|
||||
Assert.AreEqual("Binding Changed", label.Text);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task VisualPropagationPageLevel()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
ContentPage page = new ContentPage();
|
||||
shell.Items.Add(CreateShellItem(page));
|
||||
|
||||
// setup title view
|
||||
StackLayout titleView = new StackLayout() { BackgroundColor = Color.White };
|
||||
Button button = new Button();
|
||||
titleView.Children.Add(button);
|
||||
Shell.SetTitleView(page, titleView);
|
||||
IVisualController visualController = button as IVisualController;
|
||||
|
||||
|
||||
Assert.AreEqual(page, titleView.Parent);
|
||||
|
||||
Assert.AreEqual(VisualMarker.Default, ((IVisualController)button).EffectiveVisual);
|
||||
page.Visual = VisualMarker.Material;
|
||||
Assert.AreEqual(VisualMarker.Material, ((IVisualController)button).EffectiveVisual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task VisualPropagationShellLevel()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
ContentPage page = new ContentPage();
|
||||
shell.Items.Add(CreateShellItem(page));
|
||||
|
||||
// setup title view
|
||||
StackLayout titleView = new StackLayout() { BackgroundColor = Color.White };
|
||||
Button button = new Button();
|
||||
titleView.Children.Add(button);
|
||||
Shell.SetTitleView(page, titleView);
|
||||
IVisualController visualController = button as IVisualController;
|
||||
|
||||
|
||||
Assert.AreEqual(page, titleView.Parent);
|
||||
Assert.AreEqual(VisualMarker.Default, ((IVisualController)button).EffectiveVisual);
|
||||
shell.Visual = VisualMarker.Material;
|
||||
Assert.AreEqual(VisualMarker.Material, ((IVisualController)button).EffectiveVisual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FlyoutViewVisualPropagation()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
ContentPage page = new ContentPage();
|
||||
shell.Items.Add(CreateShellItem(page));
|
||||
|
||||
|
||||
// setup title view
|
||||
StackLayout flyoutView = new StackLayout() { BackgroundColor = Color.White };
|
||||
Button button = new Button();
|
||||
flyoutView.Children.Add(button);
|
||||
shell.SetValue(Shell.FlyoutHeaderProperty, flyoutView);
|
||||
|
||||
IVisualController visualController = button as IVisualController;
|
||||
Assert.AreEqual(VisualMarker.Default, visualController.EffectiveVisual);
|
||||
shell.Visual = VisualMarker.Material;
|
||||
Assert.AreEqual(VisualMarker.Material, visualController.EffectiveVisual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task FlyoutViewBindingContext()
|
||||
{
|
||||
Shell shell = new Shell();
|
||||
ContentPage page = new ContentPage();
|
||||
shell.Items.Add(CreateShellItem(page));
|
||||
shell.BindingContext = new { Text = "Binding" };
|
||||
|
||||
// setup title view
|
||||
StackLayout flyoutView = new StackLayout() { BackgroundColor = Color.White };
|
||||
Label label = new Label();
|
||||
label.SetBinding(Label.TextProperty, "Text");
|
||||
flyoutView.Children.Add(label);
|
||||
shell.SetValue(Shell.FlyoutHeaderProperty, flyoutView);
|
||||
|
||||
Assert.AreEqual("Binding", label.Text);
|
||||
shell.BindingContext = new { Text = "Binding Changed" };
|
||||
Assert.AreEqual("Binding Changed", label.Text);
|
||||
shell.SetValue(Shell.FlyoutHeaderProperty, new ContentView());
|
||||
Assert.AreEqual(null, flyoutView.BindingContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -202,6 +202,9 @@ namespace Xamarin.Forms
|
|||
|
||||
if (Shell.GetSearchHandler(this) is SearchHandler searchHandler)
|
||||
SetInheritedBindingContext(searchHandler, BindingContext);
|
||||
|
||||
if (Shell.GetTitleView(this) is View titleView)
|
||||
SetInheritedBindingContext(titleView, BindingContext);
|
||||
}
|
||||
|
||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||
|
|
|
@ -49,6 +49,9 @@ namespace Xamarin.Forms
|
|||
get { return _effectiveVisual; }
|
||||
set
|
||||
{
|
||||
if (value == _effectiveVisual)
|
||||
return;
|
||||
|
||||
_effectiveVisual = value;
|
||||
OnPropertyChanged(VisualElement.VisualProperty.PropertyName);
|
||||
}
|
||||
|
|
|
@ -338,6 +338,10 @@ namespace Xamarin.Forms
|
|||
{
|
||||
base.OnPropertyChanged(propertyName);
|
||||
|
||||
IPropertyPropagationController titleView = Shell.GetTitleView(this) ?? NavigationPage.GetTitleView(this);
|
||||
if(titleView != null)
|
||||
PropertyPropagationExtensions.PropagatePropertyChanged(propertyName, this, new[] { titleView });
|
||||
|
||||
if (_effects == null || _effects.Count == 0)
|
||||
return;
|
||||
|
||||
|
|
|
@ -67,6 +67,9 @@ namespace Xamarin.Forms
|
|||
get { return _effectiveVisual; }
|
||||
set
|
||||
{
|
||||
if (value == _effectiveVisual)
|
||||
return;
|
||||
|
||||
_effectiveVisual = value;
|
||||
OnPropertyChanged(VisualElement.VisualProperty.PropertyName);
|
||||
}
|
||||
|
|
|
@ -16,8 +16,6 @@ namespace Xamarin.Forms
|
|||
|
||||
public interface IShellController : IPageController
|
||||
{
|
||||
event EventHandler HeaderChanged;
|
||||
|
||||
event EventHandler StructureChanged;
|
||||
|
||||
View FlyoutHeader { get; }
|
||||
|
|
|
@ -187,19 +187,12 @@ namespace Xamarin.Forms
|
|||
List<(IAppearanceObserver Observer, Element Pivot)> _appearanceObservers = new List<(IAppearanceObserver Observer, Element Pivot)>();
|
||||
List<IFlyoutBehaviorObserver> _flyoutBehaviorObservers = new List<IFlyoutBehaviorObserver>();
|
||||
|
||||
event EventHandler IShellController.HeaderChanged
|
||||
{
|
||||
add { _headerChanged += value; }
|
||||
remove { _headerChanged -= value; }
|
||||
}
|
||||
|
||||
event EventHandler IShellController.StructureChanged
|
||||
{
|
||||
add { _structureChanged += value; }
|
||||
remove { _structureChanged -= value; }
|
||||
}
|
||||
|
||||
event EventHandler _headerChanged;
|
||||
event EventHandler _structureChanged;
|
||||
|
||||
View IShellController.FlyoutHeader => FlyoutHeaderView;
|
||||
|
@ -708,10 +701,16 @@ namespace Xamarin.Forms
|
|||
_flyoutHeaderView = value;
|
||||
if (_flyoutHeaderView != null)
|
||||
OnChildAdded(_flyoutHeaderView);
|
||||
_headerChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnBindingContextChanged()
|
||||
{
|
||||
base.OnBindingContextChanged();
|
||||
if (FlyoutHeaderView != null)
|
||||
SetInheritedBindingContext(FlyoutHeaderView, BindingContext);
|
||||
}
|
||||
|
||||
List<List<Element>> IShellController.GenerateFlyoutGrouping()
|
||||
{
|
||||
// The idea here is to create grouping such that the Flyout would
|
||||
|
@ -1033,10 +1032,6 @@ namespace Xamarin.Forms
|
|||
else
|
||||
FlyoutHeaderView = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
FlyoutHeaderView.BindingContext = newVal;
|
||||
}
|
||||
}
|
||||
|
||||
void OnFlyoutHeaderTemplateChanged(DataTemplate oldValue, DataTemplate newValue)
|
||||
|
@ -1051,7 +1046,6 @@ namespace Xamarin.Forms
|
|||
else
|
||||
{
|
||||
var newHeaderView = (View)newValue.CreateContent(FlyoutHeader, this);
|
||||
newHeaderView.BindingContext = FlyoutHeader;
|
||||
FlyoutHeaderView = newHeaderView;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,7 +89,8 @@ namespace Xamarin.Forms
|
|||
|
||||
internal override ReadOnlyCollection<Element> LogicalChildrenInternal => _logicalChildrenReadOnly ?? (_logicalChildrenReadOnly = new ReadOnlyCollection<Element>(_logicalChildren));
|
||||
|
||||
Page ContentCache {
|
||||
Page ContentCache
|
||||
{
|
||||
get { return _contentCache; }
|
||||
set
|
||||
{
|
||||
|
|
|
@ -64,6 +64,9 @@ namespace Xamarin.Forms.Platform.Android
|
|||
_bottomView.SetBackgroundColor(Color.White.ToAndroid());
|
||||
_bottomView.SetOnNavigationItemSelectedListener(this);
|
||||
|
||||
if(ShellItem == null)
|
||||
throw new ArgumentException("Active Shell Item not set. Have you added any Shell Items to your Shell?", nameof(ShellItem));
|
||||
|
||||
HookEvents(ShellItem);
|
||||
SetupMenu();
|
||||
|
||||
|
|
|
@ -386,8 +386,6 @@ namespace Xamarin.Forms.Platform.Android
|
|||
}
|
||||
else
|
||||
{
|
||||
// FIXME
|
||||
titleView.Parent = _shellContext.Shell;
|
||||
_titleViewContainer = new ContainerView(context, titleView);
|
||||
_titleViewContainer.MatchHeight = _titleViewContainer.MatchWidth = true;
|
||||
_titleViewContainer.LayoutParameters = new Toolbar.LayoutParams(LP.MatchParent, LP.MatchParent)
|
||||
|
|
Загрузка…
Ссылка в новой задаче