首页 > 解决方案 > 子 ViewModel 的 PropertyChange 不会更新 Xamarin 中的 UI

问题描述

我有一个带有 Telerik TabView 的页面。这包含两个选项卡。每个选项卡都包含一个在单独文件中指定为 ContentView 的视图。每个视图都有自己的 ViewModel,在页面的 ViewModel 中引用。

在 UI 中,我使用子 ViewModels 作为 TabHeaders 中元素的 BindingContext。在初始加载时,使用的属性的值被正确加载,但是当值被更新时,UI 不会更新。为什么?

所有 ViewModel 都实现了相同的基类,该基类实现了 INotifyPropertyChanged,并且调用了使用的属性的 OnPropertyChanged() 方法,并且可以在自己的 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; }

子视图模型(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));
            }
        }
    }

页面 XAML(circle:CircleImage 中使用的子 ViewModel):

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

标签: xamarin.formspropertychangedbinding-context

解决方案


看来您没有实现IsEquipmentValid的Set方法。所以即使你改变了其他行的值,它也永远不会改变。

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

    }

推荐阅读