1
votes

I have a simple View that displays a label with a Question that is being bound from my ViewModel. now if I set the property in my constructor I see the Label displaying whatever I set it to. if I populated from my command function I do not see the label changed. The funny thing is that if I set the Title property (a simple string that has a get and set), then that changes no matter where I set it. but for some reason this particular property does not want to show the changes to it. I have tried simplifying this as much as I can. I tried to define a public string property in my ViewModel and again if I set it in the Constructor than it binds other wise if it is being set in my Command Function then it does not change.

here is my XAML

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         x:Class="Pre.MyPage"
         Title="{Binding Title}"
         Icon="about.png">
 <StackLayout  VerticalOptions="Center" HorizontalOptions="Center" >
   <Label Text="{Binding MyClassObj.Question, Mode=TwoWay}"/>  
 </StackLayout>
 </ContentPage>

Here is my Code behind

public partial class MyPage : ContentPage
{
    MyViewModel vm;
    MyViewModel ViewModel => vm ?? (vm = BindingContext as MyViewModel);
    public MyPage()
    {
        InitializeComponent();
        BindingContext = new MyViewModel(Navigation);
    }
    protected override void OnAppearing()
    {
        base.OnAppearing();
        ViewModel.LoadQuestionCommand.Execute("1");
    }
}

Here is my ViewModel

public class MyViewModel : ViewModelBase 
{
    public MyClass MyClassObj {get;set;}

    ICommand loadQuestionCommand;
    public ICommand LoadQuestionCommand =>
        loadQuestionCommand ?? (loadQuestionCommand = new Command<string>(async (f) => await LoadQuestion(f)));

    public MyViewModel(INavigation navigation) : base(navigation)
    {
        Title = "My Title";            
    }
    async Task<bool> LoadQuestion(string id)
    {
        if (IsBusy)
            return false;
        try
        {
            IsBusy = true;

            MyClassObj = await StoreManager.QuestionStore.GetQuestionById(id);   
            //MyClassObject is populated when I break here
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
        finally
        {
            IsBusy = false;
        }
        return true;
    }
1

1 Answers

1
votes

I don't see where you are firing the INofityPropertyChanged event for your MyClassObj property.

Instead of just:

public MyClass MyClassObj {get;set;}

you should have something like:

MyClass myClassObj;
public MyClass MyClassObj 
{
    get {return myClassObj;}
    set
    {
        //if they are the same you should not fire the event.
        //but since it's a custom object you will need to override the Equals
        // of course you could remove this validation.
        if(myClassObj.Equals(value))
            return;

        myClassObj = value;

        //This method or something has to be in your VieModelBase,  similar.
        NotifyPropertyChanged(nameof(MyClassObj));
   }
 }    

Where the last method

NotifyPropertyChanged(nameof(MyClassObj));

is who notifies the View about the changes.