locked
Databinding - return bool status based on Enum RRS feed

  • Question

  • User364376 posted

    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));
            }
        }
    
    Sunday, May 12, 2019 8:30 AM

Answers

  • User89714 posted

    @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.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Sunday, May 12, 2019 9:51 AM
  • User364376 posted

    @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

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Sunday, May 12, 2019 10:01 PM

All replies

  • User89714 posted

    @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.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Sunday, May 12, 2019 9:51 AM
  • User364376 posted

    @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

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Sunday, May 12, 2019 10:01 PM
  • User89714 posted

    @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

    Sunday, May 12, 2019 10:45 PM