XAML binding no updating after PropertyChanged

AndrewRaperAndrewRaper USMember ✭✭

Hi all, Im having a problem with my bindings not updating after the property changed has been fired. We're trying to create reusable controls/content views throughout the app that have their own viewmodel where the bindings take place.
This is what we have so far

The content view

<ContentView
         xmlns:base="clr-namespace:MobilcomDebitel.Core.LayoutModels.Base;assembly=MobilcomDebitel.Core"
         x:Class="MobilcomDebitel.Core.Layouts.ContentViews.Cards.CostSinceLastBillCardContentView"
         base:LayoutModelLocator.AutoWireViewModel="true">
<ContentView.Content>
    <StackLayout>
        <Label Text="{Binding BillCost, Mode=TwoWay}" VerticalOptions="Center" HorizontalOptions="Center" 
             Font="{StaticResource HeadlineFont}" TextColor="{StaticResource Secondary}"/>
        <Label Text="{Binding BillDate}" VerticalOptions="Center" HorizontalOptions="Center" 
             Font="{StaticResource BodyFont}" TextColor="{StaticResource Secondary}"/>
    </StackLayout>
</ContentView.Content>

the contentViewModel

class CostSinceLastBillCardContentViewModel : BaseContentViewModel
{
    private string _billCost;
    private string _billDate = "fheuisf";

    public CostSinceLastBillCardContentViewModel()
    {
    }

    public string BillCost
    {
        get
        {
            System.Diagnostics.Debug.WriteLine("Getting BillCost " + _billCost);
            return _billCost;
        }
        set
        {
            System.Diagnostics.Debug.WriteLine("Setting BillCost " + value);
            _billCost = value;
            RaisePropertyChanged(() => BillCost);
        }
    }

    public string BillDate
    {
        get => _billDate;
        set
        {
            _billDate = value;
            OnPropertyChanged();
        }
    }
}

the Content Page its placed in

<ContentPage
         xmlns:cards="clr-namespace:MobilcomDebitel.Core.Layouts.ContentViews.Cards;assembly=MobilcomDebitel.Core"
         xmlns:base="clr-namespace:MobilcomDebitel.Core.LayoutModels.Base;assembly=MobilcomDebitel.Core"
         x:Class="MobilcomDebitel.Core.Layouts.ContentPages.Samples.Cards.CostSinceLastBillCardSampleContentPage"
         base:LayoutModelLocator.AutoWireViewModel="true">
<ContentPage.Content>
    <StackLayout>
        <Label Text="Cost since last bill card" />
        <cards:CostSinceLastBillCardContentView />
    </StackLayout>
</ContentPage.Content>

The contentPageModel

class CostSinceLastBillCardSampleContentPageModel : BaseContentPageModel
{
    private CostSinceLastBillCardContentViewModel _viewModel = new CostSinceLastBillCardContentViewModel();

    public CostSinceLastBillCardSampleContentPageModel(IDialogService dialogService, INavigationService navigationService) : base(dialogService, navigationService)
    {
        UpdateBindings();
    }

    private void UpdateBindings()
    {
        _viewModel.BillCost = "14.99";
        _viewModel.BillDate = "10-10-2017";
    }
}

The ContentViewModel does get the values from the PageModel, but the bindings aren't being set.

Answers

  • MeaurisMeauris NLMember

    My best guess is your base:LayoutModelLocator.AutoWireViewModel.AutoWireViewModel setting.

  • AndrewRaperAndrewRaper USMember ✭✭

    This sets the binding context, as it gets the hardcoded string for date.

  • MabroukMabrouk USMember ✭✭✭

    Hi,

    try to use this package https://www.nuget.org/packages/Refractored.MvvmHelpers

    your code can be like this :

    public class CostSinceLastBillCardContentViewModel : ObservableObject//BaseContentViewModel
        {
            // Or maybe your BaseContentViewModel inherits from  ObservableObject ...
            private string _billCost;
            private string _billDate = "fheuisf";
            public string BillCost
            {
                get
                {
                    return _billCost;
                }
                set
                {
                    _billCost = value;
                    OnPropertyChanged(nameof(BillCost));
                }
            }
    
            public string BillDate
            {
                get { return _billDate; }
                set
                {
                    _billDate = value;
                    OnPropertyChanged(nameof(BillDate));
                }
            }
        }
    

    I hope that helps,
    Mabrouk.

  • AndrewRaperAndrewRaper USMember ✭✭

    @Mabrouk the BaseViewModel inherits ObservableObject and has the implementation for OnPropertyChanged

  • MabroukMabrouk USMember ✭✭✭

    so you just set your properties as i do, it should be a solution..

  • JohnBairdJohnBaird USMember ✭✭
    edited October 11

    You don't need to go through all that:

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName] string name = "")
    {
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }

    Use the CallerMemberName and you don't have to pass any strings at all, just Call OnPropertyChanged();

  • RodyRody USMember ✭✭

    Where are you setting the binding context of the page? And also what are you setting it to?

  • AndrewRaperAndrewRaper USMember ✭✭

    The binding context is set from the autowire.

    Turns out after a lot of debugging, we didnt set the ninject binding for the viewmodels.

Sign In or Register to comment.