PropertyChange of sub-ViewModel does not update UI in Xamarin

229 views Asked by At

I have a page with a Telerik TabView. This contains two tabs. Each tab contains a view specified as ContentView in separate files. Each view has its own ViewModel, which are referenced in the ViewModel of the page.

In UI I use the sub-ViewModels as BindingContext for elements in the TabHeaders. On initial load the value of the used property is loaded correctly, but when the value is updated the UI doesn't update. Why?

All ViewModels are implementing the same base class which implements the INotifyPropertyChanged and the OnPropertyChanged() method for the used property is called and can be received in the own ViewModel.

Page-ViewModel:

    public EquipmentPageViewModel(...){
        var locator = (ViewModelLocator)Application.Current.Resources[nameof(ViewModelLocator)];
        EquipmentOverviewViewModel = locator.GetViewModel(nameof(IEquipmentOverviewViewModel)) as IEquipmentOverviewViewModel;
        CalibrationViewModel = locator.GetViewModel(nameof(ICalibrationViewModel)) as ICalibrationViewModel;
    }

    public IEquipmentOverviewViewModel EquipmentOverviewViewModel { get; private set; }
    public ICalibrationViewModel CalibrationViewModel { get; private set; }

sub-ViewModel (EquipmentOverviewViewModel):

    // property bound to an tabHeader in the page
    public bool IsEquipmentValid
    {
        get
        {
            if (OrderWorkflow != null && OrderWorkflow.IsBatchEditing)
            {
                if (Operation == null || Operation.Equipment == null)
                {
                    return false;
                }

                return IsQualityControlValid;
            }
            else
            {
                return Operation != null && Operation.Equipment != null && Operation.Equipment.IsEquipmentValid && IsQualityControlValid;
            }
        }
    }

    // property bound to an entry element in the view contained in the tab item
    public string EquipmentNumber
    {
        get
        {
            return Equipment.EquipmentNumber;
        }

        set
        {
            if (value != Equipment.EquipmentNumber)
            {
                Equipment.EquipmentNumber = value;
                OnPropertyChanged(nameof(EquipmentNumber));
                OnPropertyChanged(nameof(IsEquipmentValid));
            }
        }
    }

Page XAML (sub-ViewModel used in circle:CircleImage):

            <ControlTemplate x:Key="EquipmentHeaderTemplate">
                <Grid BackgroundColor="Transparent">
                    <BoxView IsVisible="{TemplateBinding IsSelected}"
                             BackgroundColor="#007bff"
                             VerticalOptions="End"
                             Margin="0, 5, 0, 0"
                             HeightRequest="3"/>
                    <StackLayout Orientation="Horizontal"
                                 Margin="15"
                                 VerticalOptions="CenterAndExpand"
                                 HorizontalOptions="CenterAndExpand">
                        <!-- Validation mark -->
 problem here--->       <circle:CircleImage BindingContext="{Binding EquipmentOverviewViewModel}"
                                            WidthRequest="10"
                                            HeightRequest="10"
                                            BorderColor="Transparent"
                                            BorderThickness="1"
                                            FillColor="#FF3B30"
                                            Aspect="Fill"
                                            IsVisible="{Binding IsEquipmentValid, Converter={StaticResource BooleanInverterConverter}, Mode=TwoWay}"
                                            Margin="5, 5, 5, 0"
                                            HorizontalOptions="Center"
                                            VerticalOptions="Center" />
                        <iconize:IconLabel Text="ion-ios-construct"
                                           TextColor="#007bff"
                                           VerticalOptions="CenterAndExpand"/>
                        <Label Text="{Binding [OrderOperationDetailsPage_PivotItemEquipmentHeader], Source={StaticResource LocalizedString}}"
                               TextColor="#007bff"
                               Margin="10, 0, 0, 0"
                               VerticalOptions="CenterAndExpand"/>
                    </StackLayout>
                </Grid>
            </ControlTemplate>

...

                        <primitives:TabViewItem.Header>
                            <primitives:TabViewHeaderItem ControlTemplate="{StaticResource EquipmentHeaderTemplate}"
                                                          IsVisible="{Binding IsCalibrationAllowed}"/>
                        </primitives:TabViewItem.Header>
                        <primitives:TabViewItem.Content>
                            <equipment:EquipmentView></equipment:EquipmentView>
                        </primitives:TabViewItem.Content>
1

There are 1 answers

3
Lucas Zhang On

It seems that you didn't implement the Set method of IsEquipmentValid . So even if you change the value in other lines , it will never been changed .

 public bool IsEquipmentValid
    {
        get
        {
            if (OrderWorkflow != null && OrderWorkflow.IsBatchEditing)
            {
                if (Operation == null || Operation.Equipment == null)
                {
                    return false;
                }

                return IsQualityControlValid;
            }
            else
            {
                return Operation != null && Operation.Equipment != null && Operation.Equipment.IsEquipmentValid && IsQualityControlValid;
            }
        }

        set
        {
          if (value != IsQualityControlValid)
            {
               value = IsQualityControlValid;
               OnPropertyChanged(nameof(IsEquipmentValid));
            }    
        }

    }