Xamarin Forms - how to generate an event based on Visible property changes

Viewed 1541

In my application I have certain ContentViews that need to take an action when they become visible (namely load their data). There are several events in the system that can cause them to become visible, so tying the load data operations to those is problematic as many of those events can occur one after the other. If I had a way to simply load the data when the Visible property turns "true", then I will be in a much better place.

I created a simple example of what I am trying to accomplish. Namely I need the ContentView to generate an event when the Visible property changes. It doesn't work, but I think it's close and I would appreciate someone showing me how to make it work. If I can get this example to work, then I can wrap all of my ContentViews that need this functionality in a base ContentView that delivers the event I am needing.

All the code can be found on GitHub here. If helpful, you can download the code to see the entire solution.

First I have a PanelView control defined. Notice I am binding the IsVisible property to a PanelVisible property in the code behind...

enter image description here

Then in the code behind I have two BindableProperty props, PanelVisibleProperty and ShowingProperty. PanelVisible is bound to IsVisible from above. On the propertyChanged event, I am invoking the Showing Command.

enter image description here

In my MainPage.xaml I have a button which when clicked invokes the ShowPanelView Command which sets the PanelViewVisible property and makes the PanelView display (initially hidden upon load). And, I bind the Showing Command from the PanelView to the PanelShowing Command in the model.

enter image description here

And finally, here is the MainPageModel that is bound to the page...

enter image description here

I am not getting a propertyChanged event here, and if I can get that to happen, then I think the rest of it would work fine.

enter image description here

Can anyone see what the issue is? Much thanks!

2 Answers

I figured out the issue. In my MainPage.xaml I was binding to the PanelView's IsVisible property. Instead it needed to bind to the PanelVisible property. All is working now.

Here is the updated code for MainPage.xaml. And I have updated the GitHub repo in case anyone else has a similar need.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:PanelViewControl"
             x:Class="PanelViewControl.MainPage">

    <StackLayout Margin="100">
        <Button Text="Show Panel View Control" Command="{Binding ShowPanelView}" />
        <local:PanelView PanelVisible="{Binding PanelViewVisible}" 
                         Showing="{Binding PanelShowing}">
        </local:PanelView>
    </StackLayout>

</ContentPage>

The issue is when you change the PanelViewVisible value but it is not notified to the change. To fix this issue you have to implement INotifyPropertyChanged to your model class.

Here is the Code:

  public class MainPageModel : FreshBasePageModel,INotifyPropertyChanged
  {
    public event PropertyChangedEventHandler PropertyChanged;

    public Command ShowPanelView
    {
        get
        {
            return new Command(() =>
            {
                PanelViewVisible = true;
            });
        }
    }
    bool _panelViewVisible;
    public bool PanelViewVisible
    {
        set { SetProperty(ref _panelViewVisible, value); }
        get { return _panelViewVisible; }
    }

    public Command PanelShowing
    {
        get
        {
            return new Command(() =>
            {
            });
        }
    }

    bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (Object.Equals(storage, value))
            return false;

        storage = value;
        OnPropertyChanged(propertyName);
        return true;
    }

    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Just replace with your model and check.

Related