Skip to content

Add IsVisible Property to ToolbarItem #30267

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion src/Controls/samples/Controls.Sample.Sandbox/MainPage.xaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Maui.Controls.Sample.MainPage"
xmlns:local="clr-namespace:Maui.Controls.Sample">
xmlns:local="clr-namespace:Maui.Controls.Sample"
Title="ToolbarItem IsVisible Test">
<ContentPage.ToolbarItems>
<ToolbarItem x:Name="AlwaysVisibleItem" Text="Always Visible" />
<ToolbarItem x:Name="ToggleableItem" Text="Toggle Me" />
<ToolbarItem x:Name="AnotherItem" Text="Another Item" />
</ContentPage.ToolbarItems>
<StackLayout Padding="20">
<Label Text="ToolbarItem IsVisible Test" FontSize="18" FontAttributes="Bold" />
<Label Text="This page demonstrates the new IsVisible property on ToolbarItem. Use the buttons below to toggle the visibility of toolbar items." />
<Button x:Name="ToggleButton" Text="Toggle 'Toggle Me' Item" Clicked="OnToggleClicked" />
<Button x:Name="HideAllButton" Text="Hide All Items" Clicked="OnHideAllClicked" />
<Button x:Name="ShowAllButton" Text="Show All Items" Clicked="OnShowAllClicked" />
</StackLayout>
</ContentPage>
21 changes: 21 additions & 0 deletions src/Controls/samples/Controls.Sample.Sandbox/MainPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,25 @@ public MainPage()
{
InitializeComponent();
}

private void OnToggleClicked(object sender, EventArgs e)
{
ToggleableItem.IsVisible = !ToggleableItem.IsVisible;
ToggleButton.Text = ToggleableItem.IsVisible ? "Hide 'Toggle Me' Item" : "Show 'Toggle Me' Item";
}

private void OnHideAllClicked(object sender, EventArgs e)
{
AlwaysVisibleItem.IsVisible = false;
ToggleableItem.IsVisible = false;
AnotherItem.IsVisible = false;
}

private void OnShowAllClicked(object sender, EventArgs e)
{
AlwaysVisibleItem.IsVisible = true;
ToggleableItem.IsVisible = true;
AnotherItem.IsVisible = true;
ToggleButton.Text = "Hide 'Toggle Me' Item";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1302,6 +1302,7 @@ public override void ViewDidLoad()

_tracker.Target = Child;
_tracker.AdditionalTargets = Child.GetParentPages();
_tracker.PagePropertyChanged += OnToolbarItemPropertyChanged;

UpdateToolbarItems();
}
Expand Down Expand Up @@ -1332,10 +1333,12 @@ public override void WillMoveToParentViewController(UIViewController parent)
if (parent is null)
{
_tracker.CollectionChanged -= TrackerOnCollectionChanged;
_tracker.PagePropertyChanged -= OnToolbarItemPropertyChanged;
}
else
{
_tracker.CollectionChanged += TrackerOnCollectionChanged;
_tracker.PagePropertyChanged += OnToolbarItemPropertyChanged;
}
}

Expand All @@ -1352,6 +1355,7 @@ internal void Disconnect(bool dispose)
{
_tracker.Target = null;
_tracker.CollectionChanged -= TrackerOnCollectionChanged;
_tracker.PagePropertyChanged -= OnToolbarItemPropertyChanged;
_tracker = null;
}

Expand Down Expand Up @@ -1632,6 +1636,19 @@ void TrackerOnCollectionChanged(object sender, EventArgs eventArgs)
UpdateToolbarItems();
}

void OnToolbarItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
// Handle ToolbarItem property changes, especially IsVisible
if (e.PropertyName == nameof(ToolbarItem.IsVisible) ||
e.PropertyName == nameof(ToolbarItem.Text) ||
e.PropertyName == nameof(ToolbarItem.IconImageSource) ||
e.PropertyName == nameof(ToolbarItem.Order) ||
e.PropertyName == nameof(ToolbarItem.Priority))
{
UpdateToolbarItems();
}
}

void UpdateHasBackButton()
{
if (Child is not Page child || NavigationItem.HidesBackButton == !NavigationPage.GetHasBackButton(child))
Expand Down Expand Up @@ -1683,7 +1700,7 @@ void UpdateToolbarItems()

List<UIBarButtonItem> primaries = null;
List<UIBarButtonItem> secondaries = null;
var toolbarItems = _tracker.ToolbarItems;
var toolbarItems = _tracker.ToolbarItems.Where(item => item.IsVisible);
foreach (var item in toolbarItems)
{
if (item.Order == ToolbarItemOrder.Secondary)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
override Microsoft.Maui.Controls.ContentPresenter.OnSizeAllocated(double width, double height) -> void
override Microsoft.Maui.Controls.ScrollView.OnSizeAllocated(double width, double height) -> void
override Microsoft.Maui.Controls.TemplatedView.OnSizeAllocated(double width, double height) -> void
Microsoft.Maui.Controls.ToolbarItem.IsVisible.get -> bool
Microsoft.Maui.Controls.ToolbarItem.IsVisible.set -> void
~static readonly Microsoft.Maui.Controls.ToolbarItem.IsVisibleProperty -> Microsoft.Maui.Controls.BindableProperty
virtual Microsoft.Maui.Controls.BindableProperty.CreateDefaultValueDelegate<TDeclarer, TPropertyType>.Invoke(TDeclarer bindable) -> TPropertyType
~virtual Microsoft.Maui.Controls.BindableProperty.BindingPropertyChangedDelegate.Invoke(Microsoft.Maui.Controls.BindableObject bindable, object oldValue, object newValue) -> void
~virtual Microsoft.Maui.Controls.BindableProperty.BindingPropertyChangedDelegate<TPropertyType>.Invoke(Microsoft.Maui.Controls.BindableObject bindable, TPropertyType oldValue, TPropertyType newValue) -> void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
override Microsoft.Maui.Controls.ContentPresenter.OnSizeAllocated(double width, double height) -> void
override Microsoft.Maui.Controls.ScrollView.OnSizeAllocated(double width, double height) -> void
override Microsoft.Maui.Controls.TemplatedView.OnSizeAllocated(double width, double height) -> void
Microsoft.Maui.Controls.ToolbarItem.IsVisible.get -> bool
Microsoft.Maui.Controls.ToolbarItem.IsVisible.set -> void
~static readonly Microsoft.Maui.Controls.ToolbarItem.IsVisibleProperty -> Microsoft.Maui.Controls.BindableProperty
virtual Microsoft.Maui.Controls.BindableProperty.CreateDefaultValueDelegate<TDeclarer, TPropertyType>.Invoke(TDeclarer bindable) -> TPropertyType
~virtual Microsoft.Maui.Controls.BindableProperty.BindingPropertyChangedDelegate.Invoke(Microsoft.Maui.Controls.BindableObject bindable, object oldValue, object newValue) -> void
~virtual Microsoft.Maui.Controls.BindableProperty.BindingPropertyChangedDelegate<TPropertyType>.Invoke(Microsoft.Maui.Controls.BindableObject bindable, TPropertyType oldValue, TPropertyType newValue) -> void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
override Microsoft.Maui.Controls.ContentPresenter.OnSizeAllocated(double width, double height) -> void
override Microsoft.Maui.Controls.ScrollView.OnSizeAllocated(double width, double height) -> void
override Microsoft.Maui.Controls.TemplatedView.OnSizeAllocated(double width, double height) -> void
Microsoft.Maui.Controls.ToolbarItem.IsVisible.get -> bool
Microsoft.Maui.Controls.ToolbarItem.IsVisible.set -> void
~static readonly Microsoft.Maui.Controls.ToolbarItem.IsVisibleProperty -> Microsoft.Maui.Controls.BindableProperty
virtual Microsoft.Maui.Controls.BindableProperty.CreateDefaultValueDelegate<TDeclarer, TPropertyType>.Invoke(TDeclarer bindable) -> TPropertyType
~virtual Microsoft.Maui.Controls.BindableProperty.BindingPropertyChangedDelegate.Invoke(Microsoft.Maui.Controls.BindableObject bindable, object oldValue, object newValue) -> void
~virtual Microsoft.Maui.Controls.BindableProperty.BindingPropertyChangedDelegate<TPropertyType>.Invoke(Microsoft.Maui.Controls.BindableObject bindable, TPropertyType oldValue, TPropertyType newValue) -> void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
override Microsoft.Maui.Controls.ContentPresenter.OnSizeAllocated(double width, double height) -> void
override Microsoft.Maui.Controls.ScrollView.OnSizeAllocated(double width, double height) -> void
override Microsoft.Maui.Controls.TemplatedView.OnSizeAllocated(double width, double height) -> void
Microsoft.Maui.Controls.ToolbarItem.IsVisible.get -> bool
Microsoft.Maui.Controls.ToolbarItem.IsVisible.set -> void
~static readonly Microsoft.Maui.Controls.ToolbarItem.IsVisibleProperty -> Microsoft.Maui.Controls.BindableProperty
virtual Microsoft.Maui.Controls.BindableProperty.CreateDefaultValueDelegate<TDeclarer, TPropertyType>.Invoke(TDeclarer bindable) -> TPropertyType
~virtual Microsoft.Maui.Controls.BindableProperty.BindingPropertyChangedDelegate.Invoke(Microsoft.Maui.Controls.BindableObject bindable, object oldValue, object newValue) -> void
~virtual Microsoft.Maui.Controls.BindableProperty.BindingPropertyChangedDelegate<TPropertyType>.Invoke(Microsoft.Maui.Controls.BindableObject bindable, TPropertyType oldValue, TPropertyType newValue) -> void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
override Microsoft.Maui.Controls.ContentPresenter.OnSizeAllocated(double width, double height) -> void
override Microsoft.Maui.Controls.ScrollView.OnSizeAllocated(double width, double height) -> void
override Microsoft.Maui.Controls.TemplatedView.OnSizeAllocated(double width, double height) -> void
Microsoft.Maui.Controls.ToolbarItem.IsVisible.get -> bool
Microsoft.Maui.Controls.ToolbarItem.IsVisible.set -> void
~static readonly Microsoft.Maui.Controls.ToolbarItem.IsVisibleProperty -> Microsoft.Maui.Controls.BindableProperty
virtual Microsoft.Maui.Controls.BindableProperty.CreateDefaultValueDelegate<TDeclarer, TPropertyType>.Invoke(TDeclarer bindable) -> TPropertyType
~virtual Microsoft.Maui.Controls.BindableProperty.BindingPropertyChangedDelegate.Invoke(Microsoft.Maui.Controls.BindableObject bindable, object oldValue, object newValue) -> void
~virtual Microsoft.Maui.Controls.BindableProperty.BindingPropertyChangedDelegate<TPropertyType>.Invoke(Microsoft.Maui.Controls.BindableObject bindable, TPropertyType oldValue, TPropertyType newValue) -> void
Expand Down
3 changes: 3 additions & 0 deletions src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
override Microsoft.Maui.Controls.ContentPresenter.OnSizeAllocated(double width, double height) -> void
override Microsoft.Maui.Controls.ScrollView.OnSizeAllocated(double width, double height) -> void
override Microsoft.Maui.Controls.TemplatedView.OnSizeAllocated(double width, double height) -> void
Microsoft.Maui.Controls.ToolbarItem.IsVisible.get -> bool
Microsoft.Maui.Controls.ToolbarItem.IsVisible.set -> void
~static readonly Microsoft.Maui.Controls.ToolbarItem.IsVisibleProperty -> Microsoft.Maui.Controls.BindableProperty
virtual Microsoft.Maui.Controls.BindableProperty.CreateDefaultValueDelegate<TDeclarer, TPropertyType>.Invoke(TDeclarer bindable) -> TPropertyType
~virtual Microsoft.Maui.Controls.BindableProperty.BindingPropertyChangedDelegate.Invoke(Microsoft.Maui.Controls.BindableObject bindable, object oldValue, object newValue) -> void
~virtual Microsoft.Maui.Controls.BindableProperty.BindingPropertyChangedDelegate<TPropertyType>.Invoke(Microsoft.Maui.Controls.BindableObject bindable, TPropertyType oldValue, TPropertyType newValue) -> void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
override Microsoft.Maui.Controls.ScrollView.OnSizeAllocated(double width, double height) -> void
override Microsoft.Maui.Controls.TemplatedView.OnSizeAllocated(double width, double height) -> void
override Microsoft.Maui.Controls.ContentPresenter.OnSizeAllocated(double width, double height) -> void
Microsoft.Maui.Controls.ToolbarItem.IsVisible.get -> bool
Microsoft.Maui.Controls.ToolbarItem.IsVisible.set -> void
~static readonly Microsoft.Maui.Controls.ToolbarItem.IsVisibleProperty -> Microsoft.Maui.Controls.BindableProperty
virtual Microsoft.Maui.Controls.BindableProperty.CreateDefaultValueDelegate<TDeclarer, TPropertyType>.Invoke(TDeclarer bindable) -> TPropertyType
~virtual Microsoft.Maui.Controls.BindableProperty.BindingPropertyChangedDelegate.Invoke(Microsoft.Maui.Controls.BindableObject bindable, object oldValue, object newValue) -> void
~virtual Microsoft.Maui.Controls.BindableProperty.BindingPropertyChangedDelegate<TPropertyType>.Invoke(Microsoft.Maui.Controls.BindableObject bindable, TPropertyType oldValue, TPropertyType newValue) -> void
Expand Down
5 changes: 3 additions & 2 deletions src/Controls/src/Core/Toolbar/Toolbar.Android.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Android.Content;
using Android.Runtime;
using Android.Views;
Expand Down Expand Up @@ -47,7 +48,7 @@ partial void OnHandlerChanging(IElementHandler oldHandler, IElementHandler newHa

void OnToolbarItemPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
var toolbarItems = ToolbarItems;
var toolbarItems = ToolbarItems?.Where(item => item.IsVisible);
List<ToolbarItem> newToolBarItems = new List<ToolbarItem>();
if (toolbarItems != null)
newToolBarItems.AddRange(toolbarItems);
Expand All @@ -69,7 +70,7 @@ void UpdateMenu()
if (_currentMenuItems == null)
return;

PlatformView.UpdateMenuItems(ToolbarItems, MauiContext, BarTextColor, OnToolbarItemPropertyChanged, _currentMenuItems, _currentToolbarItems, UpdateMenuItemIcon);
PlatformView.UpdateMenuItems(ToolbarItems?.Where(item => item.IsVisible), MauiContext, BarTextColor, OnToolbarItemPropertyChanged, _currentMenuItems, _currentToolbarItems, UpdateMenuItemIcon);
}

void UpdateTitleView()
Expand Down
5 changes: 3 additions & 2 deletions src/Controls/src/Core/Toolbar/Toolbar.Windows.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Microsoft.Maui.Controls.Platform;
using Microsoft.Maui.Graphics;
using Microsoft.UI.Xaml.Controls;
Expand Down Expand Up @@ -40,7 +41,7 @@ internal void UpdateMenu()
commandBar.PrimaryCommands.Clear();
commandBar.SecondaryCommands.Clear();

List<ToolbarItem> toolbarItems = new List<ToolbarItem>(ToolbarItems ?? Array.Empty<ToolbarItem>());
List<ToolbarItem> toolbarItems = new List<ToolbarItem>(ToolbarItems?.Where(item => item.IsVisible) ?? Array.Empty<ToolbarItem>());

foreach (ToolbarItem item in toolbarItems)
{
Expand Down Expand Up @@ -98,7 +99,7 @@ internal void OnToolbarItemPropertyChanged(object? sender, PropertyChangedEventA

if (e.PropertyName == nameof(ToolbarItem.Text) || e.PropertyName == nameof(ToolbarItem.IconImageSource))
{
var toolbarItems = new List<ToolbarItem>(ToolbarItems ?? Array.Empty<ToolbarItem>());
var toolbarItems = new List<ToolbarItem>(ToolbarItems?.Where(item => item.IsVisible) ?? Array.Empty<ToolbarItem>());
SetDefaultLabelPosition(commandBar, toolbarItems);
}
}
Expand Down
25 changes: 25 additions & 0 deletions src/Controls/src/Core/Toolbar/ToolbarItem.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#nullable disable
using System;
using System.Collections.Generic;

namespace Microsoft.Maui.Controls
{
Expand All @@ -14,6 +15,9 @@ public class ToolbarItem : MenuItem

static readonly BindableProperty PriorityProperty = BindableProperty.Create(nameof(Priority), typeof(int), typeof(ToolbarItem), 0);

/// <summary>Bindable property for <see cref="IsVisible"/>.</summary>
public static readonly BindableProperty IsVisibleProperty = BindableProperty.Create(nameof(IsVisible), typeof(bool), typeof(ToolbarItem), true, propertyChanged: OnIsVisiblePropertyChanged);

/// <include file="../../docs/Microsoft.Maui.Controls/ToolbarItem.xml" path="//Member[@MemberName='.ctor'][1]/Docs/*" />
public ToolbarItem()
{
Expand Down Expand Up @@ -45,5 +49,26 @@ public int Priority
get { return (int)GetValue(PriorityProperty); }
set { SetValue(PriorityProperty, value); }
}

/// <include file="../../docs/Microsoft.Maui.Controls/ToolbarItem.xml" path="//Member[@MemberName='IsVisible']/Docs/*" />
public bool IsVisible
{
get { return (bool)GetValue(IsVisibleProperty); }
set { SetValue(IsVisibleProperty, value); }
}

static void OnIsVisiblePropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
if (bindable is not ToolbarItem item)
return;

// Find the page that contains this toolbar item and trigger an update
if (item.Parent is Page page)
{
// Trigger a toolbar items refresh by notifying that the collection has "changed"
// This will cause the platform to rebuild the toolbar with current visible items
page.Handler?.UpdateValue(nameof(Toolbar.ToolbarItems));
}
}
}
}
73 changes: 73 additions & 0 deletions src/Controls/tests/Core.UnitTests/ToolbarItemTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,79 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
public class ToolbarItemTests
: MenuItemTests
{
[Fact]
public void IsVisibleDefaultValue()
{
var toolbarItem = new ToolbarItem();
Assert.True(toolbarItem.IsVisible);
}

[Fact]
public void IsVisibleCanBeSet()
{
var toolbarItem = new ToolbarItem();

toolbarItem.IsVisible = false;
Assert.False(toolbarItem.IsVisible);

toolbarItem.IsVisible = true;
Assert.True(toolbarItem.IsVisible);
}

[Fact]
public void IsVisiblePropertyChangedManagesToolbarItemsCollection()
{
var page = new ContentPage();
var toolbarItem = new ToolbarItem { Text = "Test" };

// Add the item to the page
page.ToolbarItems.Add(toolbarItem);
Assert.Single(page.ToolbarItems);
Assert.Contains(toolbarItem, page.ToolbarItems);

// Setting IsVisible to false should NOT remove it from the collection
// It should remain in the collection but be filtered out at the platform level
toolbarItem.IsVisible = false;
Assert.Single(page.ToolbarItems);
Assert.Contains(toolbarItem, page.ToolbarItems);
Assert.False(toolbarItem.IsVisible);

// Setting IsVisible to true should keep it in the collection
toolbarItem.IsVisible = true;
Assert.Single(page.ToolbarItems);
Assert.Contains(toolbarItem, page.ToolbarItems);
Assert.True(toolbarItem.IsVisible);
}

[Fact]
public void IsVisiblePropertyPreservesOrderByPriority()
{
var page = new ContentPage();
var item1 = new ToolbarItem { Text = "Item1", Priority = 1 };
var item2 = new ToolbarItem { Text = "Item2", Priority = 2 };
var item3 = new ToolbarItem { Text = "Item3", Priority = 3 };

// Add items to page
page.ToolbarItems.Add(item1);
page.ToolbarItems.Add(item2);
page.ToolbarItems.Add(item3);
Assert.Equal(3, page.ToolbarItems.Count);

// Hide item2 (middle priority) - should remain in collection
item2.IsVisible = false;
Assert.Equal(3, page.ToolbarItems.Count);
Assert.Contains(item1, page.ToolbarItems);
Assert.Contains(item2, page.ToolbarItems);
Assert.Contains(item3, page.ToolbarItems);
Assert.False(item2.IsVisible);

// Show item2 again - should still be in same position
item2.IsVisible = true;
Assert.Equal(3, page.ToolbarItems.Count);
Assert.Equal(item1, page.ToolbarItems[0]);
Assert.Equal(item2, page.ToolbarItems[1]);
Assert.Equal(item3, page.ToolbarItems[2]);
Assert.True(item2.IsVisible);
}
}
}
Loading