0

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>
double-beep
  • 5,031
  • 17
  • 33
  • 41
das.flaigsi
  • 89
  • 1
  • 7

1 Answers1

0

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));
            }    
        }

    }
Lucas Zhang
  • 18,630
  • 3
  • 12
  • 22
  • IsQualityControlValid also doesn't have a **Set** method. Both properties check multiple conditions. The property **EquipmentNumber** can impact this conditions, therefore the OnPropertyChanged for IsEquipmentValid is called in its set method. For elements of the view itself this works fine, but not for elements of the page which includes the view. – das.flaigsi Jul 21 '20 at 11:47
  • 1
    You could post a sample which contains the issue so that I can test it on my side directly – Lucas Zhang Jul 21 '20 at 11:59
  • Thank you. While creating an example I found the mistake. I assumed another behavior of the locator.GetViewModel() method. I thought the implementation returns the one instance stored in the used container. But this was not the case. I got a new instance, therefore I had an instance used by the UI and one used in the logic. That can't work. – das.flaigsi Aug 18 '20 at 09:36