Add Page.ToolbarItems support
This commit is contained in:
Родитель
e5b2a6d394
Коммит
83343727fe
|
@ -1,30 +1,38 @@
|
|||
<ContentPage Title="Shell Properties">
|
||||
<ShellProperties NavBarIsVisible="navBarVisible"
|
||||
TabBarIsVisible="tabBarVisible"
|
||||
TitleColor="titleColor" />
|
||||
<ContentPage @ref="page">
|
||||
<ToolbarItems>
|
||||
<ToolbarItem Text="Help" OnClick="ShowHelp" />
|
||||
</ToolbarItems>
|
||||
|
||||
<StackLayout>
|
||||
<StackLayout Orientation="StackOrientation.Horizontal">
|
||||
<Label Text="Enable NavBar: " />
|
||||
<CheckBox @bind-IsChecked="navBarVisible" />
|
||||
<ChildContent>
|
||||
<ShellProperties NavBarIsVisible="navBarVisible"
|
||||
TabBarIsVisible="tabBarVisible"
|
||||
TitleColor="titleColor" />
|
||||
|
||||
<StackLayout>
|
||||
<StackLayout Orientation="StackOrientation.Horizontal">
|
||||
<Label Text="Enable NavBar: " />
|
||||
<CheckBox @bind-IsChecked="navBarVisible" />
|
||||
</StackLayout>
|
||||
<StackLayout Orientation="StackOrientation.Horizontal">
|
||||
<Label Text="Enable TabBar: " />
|
||||
<CheckBox @bind-IsChecked="tabBarVisible" />
|
||||
</StackLayout>
|
||||
<Button Text="Change Title Color" OnClick="ChangeTitleColor" />
|
||||
</StackLayout>
|
||||
<StackLayout Orientation="StackOrientation.Horizontal">
|
||||
<Label Text="Enable TabBar: " />
|
||||
<CheckBox @bind-IsChecked="tabBarVisible" />
|
||||
</StackLayout>
|
||||
<Button Text="Change Title Color" OnClick="ChangeTitleColor" />
|
||||
</StackLayout>
|
||||
</ChildContent>
|
||||
</ContentPage>
|
||||
|
||||
@code{
|
||||
Microsoft.MobileBlazorBindings.Elements.Page page;
|
||||
|
||||
bool navBarVisible = true;
|
||||
bool tabBarVisible = true;
|
||||
Color? titleColor;
|
||||
|
||||
List<Color> colors = new List<Color> {
|
||||
Color.Red,
|
||||
Color.Green,
|
||||
Color.Blue
|
||||
Color.Red,
|
||||
Color.Green,
|
||||
Color.Blue
|
||||
};
|
||||
|
||||
void ChangeTitleColor()
|
||||
|
@ -32,4 +40,9 @@
|
|||
var index = (titleColor.HasValue ? colors.IndexOf(titleColor.Value) + 1 : 0) % colors.Count;
|
||||
titleColor = colors[index];
|
||||
}
|
||||
|
||||
async Task ShowHelp()
|
||||
{
|
||||
await page.NativeControl.DisplayAlert("Help", "Some help message", "OK");
|
||||
}
|
||||
}
|
|
@ -49,6 +49,7 @@ TabbedPage
|
|||
TemplatedPage
|
||||
TemplatedView
|
||||
TimePicker
|
||||
ToolbarItem
|
||||
View
|
||||
VisualElement
|
||||
|
||||
|
|
|
@ -23,6 +23,13 @@ namespace Microsoft.MobileBlazorBindings.Core
|
|||
ElementHandlers.Add(typeof(TComponent).FullName, new ElementHandlerFactory((renderer, _) => factory(renderer)));
|
||||
}
|
||||
|
||||
public static void RegisterPropertyContentHandler<TComponent>(string propertyName,
|
||||
Func<NativeComponentRenderer, IElementHandler> factory) where TComponent : NativeControlComponentBase
|
||||
{
|
||||
var key = $"p-{typeof(TComponent).FullName}.{propertyName}";
|
||||
ElementHandlers.Add(key, new ElementHandlerFactory((renderer, _) => factory(renderer)));
|
||||
}
|
||||
|
||||
public static void RegisterElementHandler<TComponent, TControlHandler>() where TComponent : NativeControlComponentBase where TControlHandler : class, IElementHandler, new()
|
||||
{
|
||||
RegisterElementHandler<TComponent>((_, __) => new TControlHandler());
|
||||
|
|
|
@ -32,6 +32,9 @@ namespace Microsoft.MobileBlazorBindings.Core
|
|||
builder.AddContent(2, childContent);
|
||||
}
|
||||
|
||||
int sequence = 3;
|
||||
RenderAdditionalElementContent(builder, ref sequence);
|
||||
|
||||
builder.CloseElement();
|
||||
}
|
||||
|
||||
|
@ -39,6 +42,10 @@ namespace Microsoft.MobileBlazorBindings.Core
|
|||
{
|
||||
}
|
||||
|
||||
protected virtual void RenderAdditionalElementContent(RenderTreeBuilder builder, ref int sequence)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual RenderFragment GetChildContent() => null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.MobileBlazorBindings.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using XF = Xamarin.Forms;
|
||||
|
||||
namespace Microsoft.MobileBlazorBindings.Elements.Handlers
|
||||
{
|
||||
public class ListContentPropertyHandler<TElementType, TItemType> : IXamarinFormsContainerElementHandler, INonChildContainerElement where TItemType : XF.Element
|
||||
{
|
||||
private readonly Func<TElementType, IList<TItemType>> _listPropertyAccessor;
|
||||
private IList<TItemType> _propertyItems;
|
||||
|
||||
public ListContentPropertyHandler(Func<TElementType, IList<TItemType>> listPropertyAccessor)
|
||||
{
|
||||
_listPropertyAccessor = listPropertyAccessor;
|
||||
}
|
||||
|
||||
public void SetParent(object parentElement)
|
||||
{
|
||||
_propertyItems = _listPropertyAccessor((TElementType)parentElement);
|
||||
}
|
||||
|
||||
void IXamarinFormsContainerElementHandler.AddChild(XF.Element child, int physicalSiblingIndex)
|
||||
{
|
||||
if (!(child is TItemType typedChild))
|
||||
{
|
||||
throw new NotSupportedException($"Cannot add item of type {child?.GetType().Name} to a {typeof(TItemType)} collection.");
|
||||
}
|
||||
|
||||
_propertyItems.Insert(physicalSiblingIndex, typedChild);
|
||||
}
|
||||
|
||||
int IXamarinFormsContainerElementHandler.GetChildIndex(XF.Element child)
|
||||
{
|
||||
return _propertyItems.IndexOf(child as TItemType);
|
||||
}
|
||||
|
||||
void IXamarinFormsContainerElementHandler.RemoveChild(XF.Element child)
|
||||
{
|
||||
_propertyItems.Remove(child as TItemType);
|
||||
}
|
||||
|
||||
// Because this is a 'fake' element, all matters related to physical trees
|
||||
// should be no-ops.
|
||||
|
||||
object IElementHandler.TargetElement => null;
|
||||
void IElementHandler.ApplyAttribute(ulong attributeEventHandlerId, string attributeName, object attributeValue, string attributeEventUpdatesAttributeName) { }
|
||||
|
||||
XF.Element IXamarinFormsElementHandler.ElementControl => null;
|
||||
bool IXamarinFormsElementHandler.IsParented() => false;
|
||||
bool IXamarinFormsElementHandler.IsParentedTo(XF.Element parent) => false;
|
||||
|
||||
void IXamarinFormsElementHandler.SetParent(XF.Element parent)
|
||||
{
|
||||
// This should never get called. Instead, INonChildContainerElement.SetParent() implemented
|
||||
// in this class should get called.
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.MobileBlazorBindings.Core;
|
||||
using System;
|
||||
using XF = Xamarin.Forms;
|
||||
|
||||
namespace Microsoft.MobileBlazorBindings.Elements.Handlers
|
||||
{
|
||||
public partial class ToolbarItemHandler : MenuItemHandler
|
||||
{
|
||||
|
||||
public ToolbarItemHandler(NativeComponentRenderer renderer, XF.ToolbarItem toolbarItemControl) : base(renderer, toolbarItemControl)
|
||||
{
|
||||
ToolbarItemControl = toolbarItemControl ?? throw new ArgumentNullException(nameof(toolbarItemControl));
|
||||
|
||||
Initialize(renderer);
|
||||
}
|
||||
|
||||
partial void Initialize(NativeComponentRenderer renderer);
|
||||
|
||||
public XF.ToolbarItem ToolbarItemControl { get; }
|
||||
|
||||
public override void ApplyAttribute(ulong attributeEventHandlerId, string attributeName, object attributeValue, string attributeEventUpdatesAttributeName)
|
||||
{
|
||||
switch (attributeName)
|
||||
{
|
||||
case nameof(XF.ToolbarItem.Order):
|
||||
ToolbarItemControl.Order = (XF.ToolbarItemOrder)AttributeHelper.GetInt(attributeValue);
|
||||
break;
|
||||
case nameof(XF.ToolbarItem.Priority):
|
||||
ToolbarItemControl.Priority = AttributeHelper.GetInt(attributeValue);
|
||||
break;
|
||||
default:
|
||||
base.ApplyAttribute(attributeEventHandlerId, attributeName, attributeValue, attributeEventUpdatesAttributeName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,12 +2,21 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
using Microsoft.MobileBlazorBindings.Core;
|
||||
using Microsoft.MobileBlazorBindings.Elements.Handlers;
|
||||
using XF = Xamarin.Forms;
|
||||
|
||||
namespace Microsoft.MobileBlazorBindings.Elements
|
||||
{
|
||||
public partial class Page : VisualElement
|
||||
{
|
||||
static partial void RegisterAdditionalHandlers()
|
||||
{
|
||||
ElementHandlerRegistry.RegisterPropertyContentHandler<Page>(nameof(ToolbarItems),
|
||||
_ => new ListContentPropertyHandler<XF.Page, XF.ToolbarItem>(page => page.ToolbarItems));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the <see cref="Xamarin.Forms.Page" /> is about to appear.
|
||||
/// </summary>
|
||||
|
@ -18,12 +27,19 @@ namespace Microsoft.MobileBlazorBindings.Elements
|
|||
/// </summary>
|
||||
[Parameter] public EventCallback OnDisappearing { get; set; }
|
||||
|
||||
[Parameter] public RenderFragment ToolbarItems { get; set; }
|
||||
|
||||
#pragma warning disable CA1721 // Property names should not match get methods
|
||||
[Parameter] public RenderFragment ChildContent { get; set; }
|
||||
#pragma warning restore CA1721 // Property names should not match get methods
|
||||
|
||||
protected override RenderFragment GetChildContent() => ChildContent;
|
||||
|
||||
protected override void RenderAdditionalElementContent(RenderTreeBuilder builder, ref int sequence)
|
||||
{
|
||||
RenderTreeBuilderHelper.AddContentProperty(builder, sequence++, typeof(Page), nameof(ToolbarItems), ToolbarItems);
|
||||
}
|
||||
|
||||
partial void RenderAdditionalAttributes(AttributesBuilder builder)
|
||||
{
|
||||
builder.AddAttribute("onappearing", OnAppearing);
|
||||
|
|
|
@ -15,6 +15,8 @@ namespace Microsoft.MobileBlazorBindings.Elements
|
|||
{
|
||||
ElementHandlerRegistry.RegisterElementHandler<Page>(
|
||||
renderer => new PageHandler(renderer, new XF.Page()));
|
||||
|
||||
RegisterAdditionalHandlers();
|
||||
}
|
||||
|
||||
[Parameter] public XF.ImageSource BackgroundImageSource { get; set; }
|
||||
|
@ -66,5 +68,7 @@ namespace Microsoft.MobileBlazorBindings.Elements
|
|||
}
|
||||
|
||||
partial void RenderAdditionalAttributes(AttributesBuilder builder);
|
||||
|
||||
static partial void RegisterAdditionalHandlers();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
using Microsoft.MobileBlazorBindings.Core;
|
||||
|
||||
namespace Microsoft.MobileBlazorBindings.Elements
|
||||
{
|
||||
/// <summary>
|
||||
/// The only purpose of this type is to wrap content property handler, since currently renderer does not allow
|
||||
/// handlers without corresponding component.
|
||||
/// </summary>
|
||||
#pragma warning disable CA1812 // Avoid uninstantiated internal classes. Class is used generically.
|
||||
internal class PropertyWrapperComponent : NativeControlComponentBase
|
||||
#pragma warning restore CA1812 // Avoid uninstantiated internal classes
|
||||
{
|
||||
[Parameter] public RenderFragment ChildContent { get; set; }
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
ChildContent(builder);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.MobileBlazorBindings.Core;
|
||||
using Microsoft.MobileBlazorBindings.Elements.Handlers;
|
||||
using System.Threading.Tasks;
|
||||
using XF = Xamarin.Forms;
|
||||
|
||||
namespace Microsoft.MobileBlazorBindings.Elements
|
||||
{
|
||||
public partial class ToolbarItem : MenuItem
|
||||
{
|
||||
static ToolbarItem()
|
||||
{
|
||||
ElementHandlerRegistry.RegisterElementHandler<ToolbarItem>(
|
||||
renderer => new ToolbarItemHandler(renderer, new XF.ToolbarItem()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that indicates on which of the primary, secondary, or default toolbar surfaces to display this <see cref="T:Xamarin.Forms.ToolbarItem" /> element.
|
||||
/// </summary>
|
||||
[Parameter] public XF.ToolbarItemOrder? Order { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the priority of this <see cref="T:Xamarin.Forms.ToolbarItem" /> element.
|
||||
/// </summary>
|
||||
[Parameter] public int? Priority { get; set; }
|
||||
|
||||
public new XF.ToolbarItem NativeControl => ((ToolbarItemHandler)ElementHandler).ToolbarItemControl;
|
||||
|
||||
protected override void RenderAttributes(AttributesBuilder builder)
|
||||
{
|
||||
base.RenderAttributes(builder);
|
||||
|
||||
if (Order != null)
|
||||
{
|
||||
builder.AddAttribute(nameof(Order), (int)Order.Value);
|
||||
}
|
||||
if (Priority != null)
|
||||
{
|
||||
builder.AddAttribute(nameof(Priority), Priority.Value);
|
||||
}
|
||||
|
||||
RenderAdditionalAttributes(builder);
|
||||
}
|
||||
|
||||
partial void RenderAdditionalAttributes(AttributesBuilder builder);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
using Microsoft.MobileBlazorBindings.Elements;
|
||||
using System;
|
||||
|
||||
namespace Microsoft.MobileBlazorBindings
|
||||
{
|
||||
public static class RenderTreeBuilderHelper
|
||||
{
|
||||
public static void AddContentProperty(RenderTreeBuilder builder, int sequence, Type containingType, string propertyName, RenderFragment content)
|
||||
{
|
||||
if (builder is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(builder));
|
||||
}
|
||||
|
||||
if (content != null)
|
||||
{
|
||||
builder.OpenRegion(sequence);
|
||||
|
||||
// Content properties are handled by separate handlers, there rendered as separate child elements.
|
||||
// Renderer does not support elements without parent components as for now,
|
||||
// therefore adding empty parent component to workaround that.
|
||||
builder.OpenComponent<PropertyWrapperComponent>(0);
|
||||
builder.AddAttribute(1, "ChildContent", (RenderFragment)(builder =>
|
||||
{
|
||||
builder.OpenElement(2, $"p-{containingType.FullName}.{propertyName}");
|
||||
builder.AddContent(3, content);
|
||||
builder.CloseElement();
|
||||
}));
|
||||
builder.CloseComponent();
|
||||
|
||||
builder.CloseRegion();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче