9
votes

I am trying to dynamically show/hide button inside Xamarin Forms ContentPage. I have two buttons in my XAML code:

<StackLayout Orientation="Vertical">

    <Button x:Name="start_btn" Clicked="startPanic">
        <Button.Text>START</Button.Text>
    </Button>

    <Button x:Name="stop_btn" IsVisible="false">
        <Button.Text>STOP</Button.Text>
    </Button>

</StackLayout>

Corresponding C# code:

public partial class PanicPage : ContentPage
{
    private Button startBtn;
    private Button stopBtn;

    public PanicPage ()
    {
        InitializeComponent ();
        startBtn = this.FindByName<Button> ("start_btn");
        stopBtn = this.FindByName<Button> ("stop_btn");
    }

    private void startPanic(object sender, EventArgs args){
        Device.BeginInvokeOnMainThread (() => {
            startBtn.IsVisible = false;
            stopBtn.IsVisible = true; //  DOESN'T WORK, button still will be hidden
        });
    }
}

When I set isVisible property in XAML, it doesn't react for any property change in event method (startPanic). How can I fix it?

4
Have you tried removing the Device.BeginInvokeOnMainThread usage? Not sure why you are using it.Paul Diston

4 Answers

11
votes

Change your code in xmal file and write properties for start and stop button

<Button x:Name="start_btn" Clicked="startPanic" IsVisible="{Binding IsStartVisible}">
    <Button.Text>START</Button.Text>
</Button>

<Button x:Name="stop_btn" IsVisible="{Binding IsStopVisible}">
    <Button.Text>STOP</Button.Text>
</Button>

In ViewModel write following property and similar for start button and set IsStopVisible =true/false based on your logic

   private bool _isStopVisible;

    public bool IsStopVisible{
        get {
            return _isStopVisible;
        }
        set {
            _isStopVisible= value;
            RaisePropertyChanged ("IsStopVisible");
        }
    }
3
votes

Maybe I'm late but I was searching this too without success. This may be useful for someone.

objectView.SetValue(IsVisibleProperty, false); // the view is GONE, not invisible
objectView.SetValue(IsVisibleProperty, true);
1
votes

It should work just fine. I copied your code and cleaned it up a bit, it shows the STOP button, then I

A few remarks:

  • use the short property where possible <Button Text="X"/>, it's easier to read
  • when you add a XAML page the IDE adds a .xaml.cs file next to it and generates another .g.cs that you don't see. The .g.cs file contains generated code that finds all the x:Name'd elements and defines placeholders for them, no need to find them by name yourself
  • all UI-initiated events are executed on the UI thread, no need to do that explicitly

Here's the XAML, same as yours just tighter and added Margin so the button is visible

<StackLayout Orientation="Vertical" Margin="20">
  <Button x:Name="start_btn" Clicked="startPanic" Text="START" />
  <Button x:Name="stop_btn" Text="STOP" IsVisible="false" />
</StackLayout>

And the code behind:

public partial class TestPage : ContentPage
{   
    public TestPage ()
    {
        InitializeComponent ();
    }

    private void startPanic(object sender, EventArgs args){
        Device.BeginInvokeOnMainThread (() => {
            start_btn.IsVisible = false;
            stop_btn.IsVisible = true;  
        });
    }
}
0
votes

Use the Visibility property of view.

for example if u want to make your button invisible you can do

if(condition)

    {

    button.Visibility=ViewStates.Invisible;

    }

    else

    {

    button.Visibility=ViewStates.Visible;

    }