TheDeveloper
TheDeveloper

Reputation: 1217

Xamarin Forms: IsVisible binding not working properly

I am trying to update the visibility of a stacklayout of a tabbed page on user interaction and it the inverse boolean doesn't seem to work right away. i have to goto another page and come back again to see the inverse boolean converter work properly. Can anyone suggest if i am missing anything.

XAML:

<page:ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    xmlns:page="clr-namespace:My.Pages"
                    x:Class="Home"
                    xmlns:converter="clr-namespace:My.Pages.ValueConverters"
.....//....>
    
        <StackLayout x:Name="stack1" Spacing="4" IsVisible="{Binding IsSomethingVisible, Converter={x:Static converter:InverseBoolConverter.Create}}">
            <Label Text="Hello" IsVisible="{Binding IsSomethingelseVisible}"/>
            <Label Text="Hi" IsVisible="{Binding IsSomethingelse2Visible}"/>
        </StackLayout>
        <StackLayout x:Name="stack2" Spacing="4" IsVisible="{Binding IsSomethingVisible}">
            <Label Text="Hello" IsVisible="{Binding IsSomethingelseVisible}"/>
            <Label Text="Hi" IsVisible="{Binding IsSomethingelse2Visible}"/>
        </StackLayout>

Converter:

public class InverseBoolConverter : IValueConverter
    {
        public static InverseBoolConverter Create {
            get {
                return new InverseBoolConverter();
            }
        }

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return !((bool)value);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return !((bool)value);
        }
    }

ViewModel:

private bool _isSomethingVisible;
        public bool IsSomethingVisible
        {
            get { return _isSomethingVisible; }
            set
            {
                _isSomethingVisible = value;
                RaisePropertyChanged(nameof(IsSomethingVisible));
            }
        }
    
Public Void OnUserInteractionCommand()
{
    DoSomething().ContinueWith((task) => {
        Device.BeginInvokeOnMainThread(() =>{ IsSomethingVisible = true;});
    });
}

Current scenario:

By default stack1 is visible but when OnUserInteractionCommand is called stack2 is visible and stack1 is also visible, user needs to go to different page and come back again then just stack2 is visible and stack1 is not visible.

Expected : When OnUserInteractionCommand is called stack2 should be visible and stack1 is not visible.

Upvotes: 2

Views: 6453

Answers (2)

Christian Baker
Christian Baker

Reputation: 11

I have no idea what you're trying to do with this line of code.

<StackLayout x:Name="stack1" Spacing="4" IsVisible="{Binding IsSomethingVisible, Converter={x:Static converter:InverseBoolConverter.Create}}">

Typically, you would register it in App.xaml so that it can be used throughout the app. That won't be the last time you need an inverse bool converter. Yoiu could also register it in the page resources.

<ContentPage.Resources>
    <converter:Visibleconverter x:Key="VisibleConverter" />
</ContentPage.Resources>

Then just access the converter as a static resource:

<StackLayout x:Name="stack1" IsVisible="{Binding IsSomethingVisible, Converter={StaticResource VisibleConverter}}">

Upvotes: 0

Cherry Bu - MSFT
Cherry Bu - MSFT

Reputation: 10356

Expected : When OnUserInteractionCommand is called stack2 should be visible and stack1 is not visible.

I modify your code about your Converter and create simple sample to test, having no problem.

<ContentPage
x:Class="FormsSample.simplecontrol.Page19"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:converter="clr-namespace:FormsSample.converter">
<ContentPage.Resources>
    <converter:Visibleconverter x:Key="VisibleConverter" />
</ContentPage.Resources>
<ContentPage.Content>
    <StackLayout>
        <StackLayout x:Name="stack1" IsVisible="{Binding IsSomethingVisible, Converter={StaticResource VisibleConverter}}">
            <Label Text="Hello" />
            <Label Text="Hi" />
            <Label Text="stack1" />
        </StackLayout>
        <StackLayout x:Name="stack2" IsVisible="{Binding IsSomethingVisible}">
            <Label Text="Hello" />
            <Label Text="Hi" />
            <Label Text="stack2" />
        </StackLayout>

        <Button
            x:Name="btn1"
            Clicked="btn1_Clicked"
            Text="change visible" />
    </StackLayout>

</ContentPage.Content>

Visibleconverter.cs:

public class Visibleconverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return !((bool)value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

I change isSomethingVisible value by button.click.

public partial class Page19 : ContentPage, INotifyPropertyChanged
{
    private bool _isSomethingVisible;
    public bool IsSomethingVisible
    {
        get { return _isSomethingVisible; }
        set
        {
            _isSomethingVisible = value;
            RaisePropertyChanged(nameof(IsSomethingVisible));
        }
    }
    public Page19()
    {
        InitializeComponent();
        this.BindingContext = this;
    }

   
    public event PropertyChangedEventHandler PropertyChanged;

    public void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private void btn1_Clicked(object sender, EventArgs e)
    {
        Device.BeginInvokeOnMainThread(() => { IsSomethingVisible = !IsSomethingVisible; });
    }
}

Upvotes: 1

Related Questions