16

I want to hide navigation bar button in xamarin. how can i do that using binding. Toolbar item doesn't have "IsVisible" property.

Following is my xaml code

Xaml code of navigation bar button

please help me to sort out this issue.

Maulik shah
  • 1,664
  • 1
  • 19
  • 45

7 Answers7

38

I would suggest to build a bindable ToolBoxItem. That way you can control the visibility through a view model property.

An implementation could look like that:

public class BindableToolbarItem : ToolbarItem
{
    public static readonly BindableProperty IsVisibleProperty = BindableProperty.Create(nameof(IsVisible), typeof(bool), typeof(BindableToolbarItem), true, BindingMode.TwoWay, propertyChanged: OnIsVisibleChanged);

    public bool IsVisible
    {
        get => (bool)GetValue(IsVisibleProperty);
        set => SetValue(IsVisibleProperty, value);
    }

    private static void OnIsVisibleChanged(BindableObject bindable, object oldvalue, object newvalue)
    {
        var item = bindable as BindableToolbarItem;

        if (item == null || item.Parent == null)
            return;

        var toolbarItems = ((ContentPage)item.Parent).ToolbarItems;

        if ((bool)newvalue && !toolbarItems.Contains(item))
        {
            Device.BeginInvokeOnMainThread(() => { toolbarItems.Add(item); });
        }
        else if (!(bool)newvalue && toolbarItems.Contains(item))
        {
            Device.BeginInvokeOnMainThread(() => { toolbarItems.Remove(item); });
        }
    }
}
tequila slammer
  • 2,821
  • 1
  • 18
  • 25
  • 2
    This is a very nice solution. However, keep in mind that the default visibility is "True" which means, you can toggle it using a binding like IsVisible="{Binding ShowToolbarItem}" from visible to hidden. With this approach, you cannot have the toolbar item hidden from the very beginning of the page lifetime (at least not with some flickering). – thomasgalliker Apr 20 '21 at 15:31
  • 1
    Question; Why Xamarin team didn't implement IsVisible property? – Nuri YILMAZ Aug 31 '21 at 10:29
  • With this approach I pretty often get an InvalidOperationException stating "collection was modified; enumeration operation may not execute" at Page.OnBindingContextChanged. This seems to be the case because in Page.OnBindingContextChanged there is a foreach-loop iterating through the pages ToolbarItems and setting the new BindingContext which seems to interfere with the above approach to remove/add the ToolbarItems. Anyone has an idea how to fix that? – Christoph Mett Dec 15 '21 at 14:22
  • Okay, I fixed it by making it async and adding a Task.Delay before doing the adding/removing of the item. – Christoph Mett Dec 15 '21 at 15:40
  • 1
    Any idea why my item.Parent is null when I try this? The BindableToolBarItem is nested in the – CraPo Oct 18 '22 at 20:33
8

As you have discovered yourself there is not IsVisible. So you will have to implement functionality like that yourself if you still want it.

Another way would be to handle it in the pages' code-behind and remove or add the toolbar item whenever needed.

Adding and removing is simple, just add and remove items to the ToolbarItems collection: ToolbarItems.RemoveAt(0); for instance will remove the first toolbar item.

Gerald Versluis
  • 30,492
  • 6
  • 73
  • 100
2

Putting @Gerald answer in action, it would be done this way:

void Done_Clicked(System.Object sender, System.EventArgs e)
{
    //Do somthing and hide the done item
    ShowDoneToolbarItem(false, (ToolbarItem)sender);
}

void Entry_Focused(System.Object sender, Xamarin.Forms.FocusEventArgs e)
{
    //Show the done item
    ShowDoneToolbarItem(true);
}

void ShowDoneToolbarItem(bool show, ToolbarItem item = null)
{
    if(show)
    {
        ToolbarItem done = new ToolbarItem();
        done.Text = "Done";
        done.Clicked += Done_Clicked;
        ToolbarItems.Add(done);
    }
    else if(item != null)
    {
        ToolbarItems.Remove(item);
    }
}

This is cleaner and works from the code behind.

Shadi
  • 2,236
  • 2
  • 22
  • 22
0

Well we need the IsVisible property for the front end, as xamarin doesn't have it, you can use Device.RuntimePlatform to check in real time which device the application is running. Since my code is in .cs of the XAML file, we can use xaml .cs to insert items into the screen.I put if () to do the logic and check if my device is on which platform, because I don't want it to display in UWP a toolbar. The code is in .cs of the XAML file:

public kingTest()
{
InitializeComponent();
if((Device.RuntimePlatform == "Android")||(Device.RuntimePlatform == "iOS"))
{
ToolbarItem toolbar = new ToolbarItem();
toolbar.IconImageSource = "ic_ToolBar.png";
this.ToolbarItems.Add(toolbar);
}

        };
0

I've achieved this easily using overloaded constructors. Here's an example:

View (add the name property):

<ContentPage x:Name="ContentPage"
    <!-- rest of the tag -->
    />

Code-behind (add the toolbar items):

public partial class ExamplePage : ContentPage
{
    public ExamplePage()
    {
        InitializeComponent();
        BindingContext = this;

        var saveToolbarItem = new ToolbarItem { Text = "Save" };
        saveToolbarItem.Clicked += YourMethodToBeRan;

        ContentPage.ToolbarItems.Add(saveToolbarItem);
    }

    public ExamplePage(Object object)
    {
        InitializeComponent();
        BindingContext = this;

        var updateToolbarItem = new ToolbarItem { Text = "Update" };
        updateToolbarItem.Clicked += YourMethodToBeRan;

        var deleteToolbarItem = new ToolbarItem { Text = "Delete" };
        deleteToolbarItem.Clicked += YourMethodToBeRan;

        ContentPage.ToolbarItems.Add(updateToolbarItem);
        ContentPage.ToolbarItems.Add(deleteToolbarItem);
    }

    // rest of the class
}

The above pseudocode will add the "Save" toolbar item when the class is instantiated with no parameter, or the "Update" and "Delete" when a parameter is provided.

This isn't as elegant as IsEnabled / IsVisible booleans but it's a step in the right direction. Following this train of thought, you could modify the children of your toolbar during runtime to "show" and "hide" by adding and removing them as children.

Good luck!

auwilliams
  • 1
  • 1
  • 2
0

I don't know if @tequila slammer's solution fully worked on Xamarin, but for us it only kind of works in .Net Maui (the evolution of Xamarin) and binding the IsVisible property to a variable.

Once the BindableToolbarItem is removed from the ContentPage's list of ToolbarItems, it is disconnected from the object that IsVisible is bound to forever.

For example: We want to use this control to hide or show a ToolbarItem that navigates to the admin screen, if I log in as the administrator on app launch, the item is there...great. If I then log out and log in as a non-admin, the item is not there...perfect. If I then log out and log in as an admin, the item is not there (the propertyChanged: OnIsVisibleChanged never fired)...:-(.

Not a big deal for us, if you want admin access then stopping the app and starting the app to log in as the admin is not a big ask.

dpTech
  • 19
  • 3
0

In the newest release with .Net 7 the workaround works never more ! The reason is because the toolbar item which revomed will destoyed !