So from what I've seen in the API Docs (http://iosapi.xamarin.com/?link=T:Xamarin.Forms.MenuItem/*) Toolbar items don't seem to have an IsVisible property.
I was able to accomplish this by defining a Binding for the "Icon" property and settings it to null when I don't want the toolbar item to display. So far, it has worked well.
Posting here so that anyone else looking to toggle visibility of toolbar items can try it out.
Posts
No, that's not supported yet. Also, making an invisible icon doesn't stop it from being tapped.
The best way to do this is to create the toolbar items, you can keep them cached/stored in a dictionary and Add and Remove them as needed depending upon functionality present. There isn't a need to make them invisible.
Hi, I also stumbled into this. I needed the Toolbar to refresh after changing
item's title/name, or after adding/removing toolbar items.
So after I make changes I invoke this small Page extension method.
Disclaimer: tested and used only on Android and Xamarin.Forms 1.2.3.
public static void ForceToolbarRedraw(this Page page) { var itemList = page.ToolbarItems.ToList(); // create copy of toolbar items page.ToolbarItems.Clear(); // remove all itemList.ForEach(ti => page.ToolbarItems.Add(ti)); // add all from list }
Adam, do you have an example of how you did this, MVVM friendly if possible!
@AnthonyHarrison.3194 - The MVVM XAML way to make ToolbarItems Visible/Not Visible (technically its removing and adding them, as you can't actually make them invisible).
#1. Create a new Control that inherits from ToolbarItem
#2. In your content pages attributes add this
x:Name="this"
and
xmlns:control="clr-namespace:Mobile.Controls"
#3. Add in your bindable toolbar items
Wow, this looks excalty like what I was looking for.
@AdamP why do you have to set the Parent manually? Doesn't ToolbarItems have valid Parent?
@ThomasBurkhart - why yes it does, thanks for the pickup. With that said you can remove the XAML reference to the parent and change accessing the parent to
var items = ((ContentPage)item.Parent).ToolbarItems;
@AdamP
I just stumbled upon this solution: http://stackoverflow.com/questions/27803038/disable-toolbaritem-xamarin-forms
Did you ever try this?
@ThomasBurkhart - I haven't tried using the CanExecute option, so I am not sure if it provides a disabled look about it when it is off, sounds like it does. But it would be easy to test out, just set the CanExecute parameter in the command you bind to.
I just tested it. It does not change the look of the icon, it just disables the Event :-(
So your solution is still the way to go.
If the result of your CanExecute callback changes you need to call ChangeCanExecute on the command object to notify any controls to update their appearance.
@adamkemp Sorry, but there is no Method ChangeCanExecute in the ICommand Interface that I could call.
@AdamP
I just tried what you said
But item.parent is always null. No Idea why.
@AdamP
I found a strange behavior in your solution. When I try to make the Icon invisible at the beginning by assigning false to my bound IsVisible Property in my ViewModell constructor nothing happens, the Icon is displayed.
When modifying the IsVisible Property later in a TextChanged Event the Icon disappears and appears as expected.
I also bound the Visibility of a normal Button to the same Property and there is works.
I now found out, that if I change the bound Property twice it works:
The ChangeCanExecute method is on the Command class. The interface has an event that fires to signal that the value of CanExecute changed, and the ChangeCanExecute method fires that event. If you're using a different implementation of the ICommand interface then just fire the event instead.
I changed it now to a standard Command:
``` SaveCommand = new Command(Save,()=>false);
and later on
```
Only thing that happens is that the ActionbarIcon does no longer react when tapped, but it stays visible. SO it looks like that this approach does not lead to the desired goal.
Expected (by me) behavior is that the toolbar buttons remain visible, but appear disabled. If it's not doing that then file a bug report here: http://bugzilla.xamarin.com
Are you running IOS or Android?
That's the expected behavior for all platforms.
Ah, sorry, misunderstood you. your wrote "expected", not observed by you.
@ThomasBurkhart - I actually experience the issue as well. I also (as a hack) place a delay then set the boolean value. But it has to be because some events are out of order, though haven't had a look to what I need to wait for before setting it.
@AdamP
So far setting the property twice works for me well. But it would be good to know where the problem is as it works with a standard Button.
There's a bug here for it
https://bugzilla.xamarin.com/show_bug.cgi?id=25661
Seems like there's been some back and forth about confirming
i posted a sample in there of the issue with Android and the icon not graying out.. Hopefully that one works (doesn't work) for them
Have you seen the last Comment https://bugzilla.xamarin.com/show_bug.cgi?id=25661#c12
There is a solution though a real cumbersome. And nothing said about IOS
Normal Buttons also don't appear disabled when CanExecute returns false. I thought that that was the whole purpose of Xamarins own implementation of Command, but it seems like they don't use it at all.
PK there's my solution for that problem.
I put the toolbaritems in my xaml like that:
In my view I subscribe my ViewModel:
And finally in my ViewModel I send the content:
If my logged user is not an admin of the current group, hide the toolbaritems.
It is probably too late, but it looks like what is happening is OnIsVisibleChanged is being called when the BinableToolbarItem is being constructed. It hasn't been attached to a parent yet.
Override OnParentSet():
"Setting the property twice" - is the cause not perhaps that the bindable property is not defaulted to true (the initial state of the button)?
For those interested in code, I have created a github repo here
@AdamP
Thanks for this adam, was really useful. I updated it slightly to make it support the new format for bindable properties, I also got an error in my app for changing the list so just made sure that was done on the UI thread. Works a treat.
Thanks again.
Always great @NMackay
I modified this code slightly as it didn't work correctly with tabbed pages having toolbar buttons.
Thanks @NMackay for those changes/fixes. They resolved some small cleanup issues I was having with old version.
@NMackay Thank you so much, I think this is the solution for the AmbiguousMatchException I was getting. I'm wondering though what change in the IsVisibleProperty it was that made it work. Is the BindingMode.TwoWay important?
For MVVM, I'm missing a step 4: change the BindableToolbarItem.IsVisible property in the view model. All I could get to work was in the view.xaml.cs, Appearing event was sufficient for me (MyBindableToolbarItemName.IsVisible = true/false;). This is only acceptable because the events that change menu visibility are always on other pages. If an event were to happen on the menu page itself, I'd be stuck.
How do I bind BindableToolbarItem.IsVisible to a property in the the viewmodel, or otherwise set BindableToolbarItem.IsVisible in the view model?
I don't understand why the binding of the Command goes to the view model binding context, but the IsVisible binding isn't working, or seems to be bound to.....itself? (IsVisible="{Binding IsVisible}")
@NMackay you should put that thing in a Github Gist, anyway - thx.
I'm using this but recently I'm getting complaints because the toolbar item shows for a second, then is hidden afterwards. I can't figure out a way to have it not visible right from the start (even when I change default). I assume it's because the default toolbaritem is visible until I hide it which gets hit later in code. Any idea how I can make it not visible from the very start and still have the Hideable tool bar listed in the XAML (rather than in codebehind)?
if (item != null && item.Parent == null)
Parent is always null
It works but toolbar does not update in my Master Page until I navigate to another page.
I tried Adding and Removing inside a Master Page event and have to navigate to update the toolbar too.
Adam,
this really works great, but i have timing issues on Droid and iOS. On UWP this does not happen. First, all Toolbaritems are shown and then that one with IsVisible = false will disappear. Do u have any workaround for this? Or can you investigate into a renderer hiding the toolbar items?
I modified the above presented code a little bit to respect the Priority order of the toolbar items when one or more become visible at various points in time. Simply doing
items.add
will result in items that become visible later (e.g. as a result of loading something in the background) not appearing at the expected location.This is the code I came up with to circumvent this:
It works on android, iOS and UWP but, as already being pointed out shows an Invisible item very shortly on Android. UWP and iOS don't seem to exhibit this annoying behaviour. This is probably because it is necessary to insert/remove the toolbar items within a background thread in order not to interfere with the parent's child list being built up when the page is initialized.
I just read https://github.com/xamarin/Xamarin.Forms/issues/3838 and it seems that we have to live with this.