maui
maui copied to clipboard
Add IsVisible Property to ToolbarItem
Description
I would love to add a IsVisible Property for the ToolbarItem
https://github.com/xamarin/Xamarin.Forms/issues/3838
Public API Changes
ToolbarItem.IsVisible=true; //new Api
Intended Use-Case
"At times you need to check if a toolbar item is visible, and to set it thus."
Related: https://xamarin.uservoice.com/forums/258559/suggestions/15508584
We've moved this issue to the Future milestone. This means that it is not going to be worked on for the coming release. We will reassess the issue following the current release and consider this item at that time.
Here is a workaround I use (EDIT: doesn't work in later version av MAUI. Scroll down for another approach). It's deeply inspired by: https://stackoverflow.com/questions/50619388/how-to-hide-navigation-toolbar-icon-in-xamarin?msclkid=79b0a582ce9f11ec8b8fcfa78892ae51
Add a custom control to your project:
internal class BindableToolbarItem : ToolbarItem
{
public static readonly BindableProperty IsVisibleProperty =
BindableProperty.Create(nameof(IsVisible), typeof(bool), typeof(BindableToolbarItem), true, BindingMode.OneWay, propertyChanged: OnIsVisibleChanged);
public bool IsVisible
{
get => (bool)GetValue(IsVisibleProperty);
set => SetValue(IsVisibleProperty, value);
}
protected override void OnParentChanged()
{
base.OnParentChanged();
RefreshVisibility();
}
private static void OnIsVisibleChanged(BindableObject bindable, object oldvalue, object newvalue)
{
var item = bindable as BindableToolbarItem;
item.RefreshVisibility();
}
private void RefreshVisibility()
{
if (Parent == null)
{
return;
}
bool value = IsVisible;
var toolbarItems = ((ContentPage) Parent).ToolbarItems;
if (value && !toolbarItems.Contains(this))
{
Application.Current.Dispatcher.Dispatch(() => { toolbarItems.Add(this); });
}
else if (!value && toolbarItems.Contains(this))
{
Application.Current.Dispatcher.Dispatch(() => { toolbarItems.Remove(this); });
}
}
}
And then use it like this:
<ContentPage.ToolbarItems>
<controls:BindableToolbarItem
Command="{Binding MyCommand}"
Text="Do stuff"
IsVisible="{Binding Model.Foo}"
Order="Primary"
Priority="1" />
</ContentPage.ToolbarItems>
@pekspro: not sure if you've noticed, but that workaround doesn't look like it works anymore with current .NET Maui. What I'm seeing is that a BindableToolbarItem that's been removed from the parent's collection of ToolbarItems will also stop receiving IsVisible binding changes. Are you seeing the same thing?
@mfeingol, yes, I have noticed that. Will post later today how I solved it. It's not pretty.
Here is my new workaround. I have my toolbar item like this:
<ContentPage.ToolbarItems>
<ToolbarItem
x:Name="ToolbarItemAlbumMode"
Text="Show album"
Order="Secondary"
Priority="0" />
</ContentPage.ToolbarItems>
And then I have a hidden swich control that I use for binding:
<VerticalStackLayout IsVisible="False">
<Switch
x:Name="ToolbarHelperAlbum"
IsToggled="{Binding HasAlbum, Mode=OneWay}"
Toggled="ToolbarHelper_ToggleChanged"
/>
</VerticalStackLayout>
And then in the code behind:
protected override void OnAppearing()
{
base.OnAppearing();
RefreshToolbarItems();
}
private void RefreshToolbarItems()
{
SetToolbarItemVisibility(ToolbarItemAlbumMode, ViewModel.HasAlbum);
}
private void ToolbarHelper_ToggleChanged(object sender, ToggledEventArgs e)
{
RefreshToolbarItems();
}
public void SetToolbarItemVisibility(ToolbarItem toolbarItem, Microsoft.Maui.Controls.Switch switchControl)
{
SetToolbarItemVisibility(toolbarItem, switchControl.IsToggled);
}
public void SetToolbarItemVisibility(ToolbarItem toolbarItem, bool value)
{
if (value && !ToolbarItems.Contains(toolbarItem))
{
ToolbarItems.Add(toolbarItem);
}
else if (!value)
{
ToolbarItems.Remove(toolbarItem);
}
}
Thanks, @pekspro. Having a shadow element to hold the binding makes sense (and is awful!)
@jfversluis I don't suppose anyone has it on the radar to do MenuItem.IsVisible
properly?
This issue comes from Xamarin and was over 4 years old from 2018 why nobody solve this big problem and everybody must work with this workaround ? The workaround don't work also with Maui if you use Modal Page after Pop the Modal Page the workaround crashed !!!
@AHComp: what kind of crash? What's the exception and stack trace?
Simple the toolbaritems freezing so the binding to an bool property in the view model don't work any more.
The toolbaritems collection still work and changed but the rendering crashed.
I test in my App if I use PushModalAsync it crashed and if I use PushAsync it work.
Same with Shell if I Set the Parameter in the Page.
I test only in android no other platform.
I don't use PushModalAsync anywhere so I can't help with that.
Why do you have to beg Microsoft for 4 years or even longer for a simple function to be implemented correctly?
https://stackoverflow.com/questions/70719111/how-do-i-add-a-toolbar-item-net-maui
You can find a lot of more stuff if you google 5 minutes.
A workaround I made for this is to just add it in the code behind. The display of this is related to the user's permission, which wont change for the life of the user's session, so it doesnt strictly need to be bindable.
Menu item that is always present goes in XAML
<ContentPage.ToolbarItems>
<ToolbarItem Text="Help" IconImageSource="help_24dp" Clicked="ShowHelpToolbarItem_Clicked" Order="Secondary"></ToolbarItem>
</ContentPage.ToolbarItems>
and the menu item that can be conditionally added goes in the code behind constructor (i have a base class which sets up a view model Model property and does the binding context linkage, you'd just need to have some kind of way in the constructor to determine if the thing should be visible. That can come from an injected service on the constructor or some other type of data access):
public partial class ItemPage : PageBase<ItemPageViewModel>
{
public ItemPage()
{
InitializeComponent();
if (Model.CanTakePicture)
{
this.ToolbarItems.Add(new ToolbarItem("Add Picture", "add_a_photo_24dp", () => PicToolbarItem_Clicked(this, null), ToolbarItemOrder.Secondary));
}
}
I try don't work with modal pages ! I have all my toolbaritems in a custom collection. And add in the constructor. The page will not reload after close the modal page.
In the newest release with .Net 7 the workaround works never more ! The reason is because the toolbar item which revomed will destoyed !
When the developers implement the visible feature ?
This is yet to be implemented. A very valid request but unfortunately not in existence yet.
When will this be implemented?
we also need this.
I also need this.
This would be a useful addition, any idea when it could be included?
I also need this.
Need this too :(
The workaround from XF crashed in .Net 8. We need a better solution for .Net 8.
It would be useful if the team gave us an explanation why it's not planned. Just closing it as not planned seems strange because clearly there's demand for this feature.