如何在 Xamarin Forms MVVM Prism 的选择器中隐藏单个元素?

How to hide a single element in a picker in Xamarin Forms MVVM Prism?

我正在使用 MVVM 棱镜。我想在我的选择器中隐藏一个元素但是。我尝试使用 IsVisible 属性 但它不起作用。

这是我的 XAML

                               <Picker
                                    HorizontalOptions="End"
                                    WidthRequest="180"
                                    HeightRequest="40"
                                    IsVisible="{Binding IsDeductibleVisible, Mode=TwoWay}"
                                    ItemsSource="{Binding Deductibles}"
                                    ItemDisplayBinding="{Binding DisplayName}"
                                    FontSize="14"
                                    SelectedItem="{Binding SelectedDeductible}">
                              <Picker.Behaviors>
                                    <behavior:EventToCommandBehavior
                                       Command="{Binding Path=BindingContext.SelectDeductibleCommand, Source={x:Reference Name=CustomizePage}}"
                                       EventName="SelectedIndexChanged"/>
                                    </Picker.Behaviors>
                                </Picker>

这是我的视图模型。第一条记录是我要隐藏的记录。删除不是一个选项,因为 DeductiblesEnum.Zero 正在计算中使用。

Deductibles = new List<Deductible>
        {
            new Deductible{ Id = (int)DeductiblesEnum.Zero, Amount = 0, DisplayName = "NIL", IsDeductibleVisible = false },
            new Deductible{ Id = (int)DeductiblesEnum.Thousand_100, Amount = 100000, DisplayName = "100,000 per insured" },
            new Deductible{ Id = (int)DeductiblesEnum.Thousand_150, Amount = 150000, DisplayName = "150,000 per insured" },
            new Deductible{ Id = (int)DeductiblesEnum.Thousand_200, Amount = 200000, DisplayName = "200,000 per insured" }
        };

您的方案是从 ViewModel 的列表中删除一个项目,并且您正在使用 MVVM 设计模式。 Prism 是一个框架,不会对此代码产生任何影响。 IsVisible 属性 之所以不起作用,是因为它不正确 属性。 IsVisiblePicker 的 属性,将确定 Picker 是否可见。

您需要做的是更改 Picker.ItemSource 以删除不需要的值。有几种方法可以解决此问题,但我将向您展示我推荐的最 Xamarin 方法:

使用值转换器

Value Converters 是一个强大的工具,无需在 ViewModel 中编写大量代码即可将 ViewModel 中的对象映射到 UI。毕竟你的 ViewModel 应该不知道它所连接的任何视图。 Read about them here.

您的 ViewModel 看起来像这样,我已将您的列表转换为 ObservableCollection,因为这是最佳做法

// BaseViewModel comes from Refractored.MVVMHelpers
public class DeductiblesViewModel : BaseViewModel
{
    public ObservableCollection<Deductible> Deductibles { get; }

    public DeductiblesViewModel()
    {
        Title = "Deductibles";

        var deductibles = new List<Deductible>
        {
            new Deductible{ Id = (int)DeductiblesEnum.Zero, Amount = 0, DisplayName = "NIL", IsDeductibleVisible = false },
            new Deductible{ Id = (int)DeductiblesEnum.Thousand_100, Amount = 100000, DisplayName = "100,000 per insured", IsDeductibleVisible = true },
            new Deductible{ Id = (int)DeductiblesEnum.Thousand_150, Amount = 150000, DisplayName = "150,000 per insured", IsDeductibleVisible = true },
            new Deductible{ Id = (int)DeductiblesEnum.Thousand_200, Amount = 200000, DisplayName = "200,000 per insured", IsDeductibleVisible = true }
        };

        Deductibles = new ObservableCollection<Deductible>(deductibles);
    }
}

然后您将创建一个新的 ValueConverter:

public class DeductibleVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value.GetType() != typeof(ObservableCollection<Deductible>))
        {
            throw new NotSupportedException($"Object must be of type: {typeof(ObservableCollection<Deductible>)}");
        }

        var deductibles = (ObservableCollection<Deductible>)value;

        return deductibles.Where(d => d.IsDeductibleVisible).ToList();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException("We won't be using this method");
    }
}

并将其添加到您的 XAML:

<ContentPage
    ...
    /* Reference the xml namespace for your converter */
    xmlns:converters="clr-namespace:YourNamespace.Converters"
    ...>

    /* Add the converter as a resource to your page (or wherever you keep your resources) */
    <ContentPage.Resources>
        <ResourceDictionary>
            <converters:DeductibleVisibilityConverter x:Key="deductibleVisibilityConverter"/>
        </ResourceDictionary>
    </ContentPage.Resources>

    <ContentPage.Content>
        <StackLayout Padding="20">
            <Label Text="Select your deductibles"/>

            /* Add the converter to your item source */
            <Picker ItemsSource="{Binding Deductibles, Converter={StaticResource deductibleVisibilityConverter}}"
                    ItemDisplayBinding="{Binding DisplayName}"/>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

现在您可以隐藏任何不想显示给 UI 的免赔额,但保留它们以供您计算!