Forum Xamarin.Forms
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

Databinding - return bool status based on Enum

Steve1000Steve1000 Member ✭✭✭

Hi,
I'm trying to show hide a contentview / text based on if the current state is Loading Data, Data Load Success, Data Load Fail. I've tried this but it doesn't seem to work.

The View doesn't update the IsVisible status when i change the selected enum option.

There's a few other values that i would want to set based on the state (e.g. error messages, other views visible / not visible) so thought this might be a better option that setting isVisible for each item in the try / catch block - but it doesn't seem to update the view currently

View:

 <myView x:Name="overlay" IsVisible="{Binding IsVisibleOverlay}"> </myView>

ViewModel:

public enum ViewModelState
{
    BeforeDataLoad,
    LoadingData,
    DataLoadSuccess,
    DataLoadFailAndRetry
}



   private ViewModelState vmState;
    public ViewModelState VMState
    {
        get => vmState;
        set
        {
            this.vmState = value;
            OnPropertyChanged(nameof(vmState));
            OnPropertyChanged(nameof(IsVisibleOverlay));
        }
    }


public async void LoadData()
    {
        Api api = new Api();
        try
        {
            vmState = ViewModelState.LoadingData
            api.GetData
            vmState.DataLoadSuccess
        }
        catch
        {
            vmState = ViewModelState.DataLoadFailAndRetry;
        }
    }



public bool IsVisibleOverlay
        {
            get 
            {
                switch(vmState)
                {
                    case ViewModelState.LoadingData:
                        return true;

                    case ViewModelState.DataLoadSuccess:
                        return false;

                    default:
                        return false;
                }
            }

        }




  public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

Best Answers

  • Steve1000Steve1000 Member ✭✭✭
    Accepted Answer

    @JohnHardman said:
    @Steve1000

    The code as posted will not compile. Post the actual code that you are using, otherwise any responses are likely to be as erroneous as the code that is shown. Also, show the entire class for the ViewModel, not just snippets.

    I cannot tell, from what has been posted, if your ViewModel is defined as implementing INotifyPropertyChanged

    Your LoadData method won't compile. In your actual code, you will want it to assign to VMState not vmState. You might only call set currently if the value has changed, but get into the habit of putting the check in the setter.

    Your IsVisibleOverlay property should be removed from the ViewModel. Your ViewModel should not know about the View having a requirement to change visibility. Instead, use a ValueConverter in your View that converts from the enum to a boolean.

    You don't show where LoadData is called. However, as a general rule, methods other than event handlers should not be declared as async void. Replace by async Task, then rename LoadData to LoadDataAsync for maintainability.

    John - thanks for the detailed explanation - i'm not a software engineer by trade so this is useful. The issue was vmState being assigned instead of VMState and that then got it working.

    Noted about the async void vs async Task i'll update that.

    I'll look into Value Converter and see how to implement this - are there any books / courses that you'd recommend for topics such as this? a lot of the tutorials i have come across are relatively basic

Answers

  • Steve1000Steve1000 Member ✭✭✭
    Accepted Answer

    @JohnHardman said:
    @Steve1000

    The code as posted will not compile. Post the actual code that you are using, otherwise any responses are likely to be as erroneous as the code that is shown. Also, show the entire class for the ViewModel, not just snippets.

    I cannot tell, from what has been posted, if your ViewModel is defined as implementing INotifyPropertyChanged

    Your LoadData method won't compile. In your actual code, you will want it to assign to VMState not vmState. You might only call set currently if the value has changed, but get into the habit of putting the check in the setter.

    Your IsVisibleOverlay property should be removed from the ViewModel. Your ViewModel should not know about the View having a requirement to change visibility. Instead, use a ValueConverter in your View that converts from the enum to a boolean.

    You don't show where LoadData is called. However, as a general rule, methods other than event handlers should not be declared as async void. Replace by async Task, then rename LoadData to LoadDataAsync for maintainability.

    John - thanks for the detailed explanation - i'm not a software engineer by trade so this is useful. The issue was vmState being assigned instead of VMState and that then got it working.

    Noted about the async void vs async Task i'll update that.

    I'll look into Value Converter and see how to implement this - are there any books / courses that you'd recommend for topics such as this? a lot of the tutorials i have come across are relatively basic

  • JohnHardmanJohnHardman GBUniversity admin

    @JohnHardman said:
    In your actual code, you will want it to assign to VMState not vmState.

    @Steve1000 - Don't forget to mark as Accepted Answer the post containing the answer :-)

    For more about ValueConverters, see https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/data-binding/converters

Sign In or Register to comment.