Xamarin - 将选择器绑定到 MVVM 命令

Xamarin - Binding a Picker to MVVM command

我正在尝试在我的 Xamarin 项目中使用 MVVM 架构,但我还不太理解它。

我有两个实体 CrCountryCrCity,我希望用户能够选择一个国家,然后根据该国家 select 一个城市。我还希望城市的选择器在用户选择国家之前“不可用”。

为此,我需要知道我的选择器上 selected 的项目,以便我可以访问我的数据库并传递该值。我该怎么做?

编辑:

它现在可以使用我现有的东西,唯一不起作用的是我的城市选择器上的 IsEnabled 属性。 正如我所说,我希望在选择国家之前禁用城市选择器。我不能使用 SelectedIndex 而不是 SelectedItem,因为我的 CrCountry 实体有一个字符串作为 id,我需要获取 selected 项目以按国家/地区过滤城市。这是我的:

我的视图模型

public class InvoiceDataViewModel : BindableObject
    {
        public InvoiceDataViewModel()
        {
            GetCountries();

        }

        private ApiService _apiService = new ApiService();
        private List<CrCountry> _countries;
        private List<CrCity> _cities;

        public List<CrCountry> Countries
        {
            get => _countries;
            set
            {
                _countries = value;
                OnPropertyChanged();
            }
        }

        public List<CrCity> Cities
        {
            get => _cities;
            set
            {
                _cities = value;
                OnPropertyChanged();

            }
        }

        private CrCountry _selectedCountry;
        public CrCountry SelectedCountry
        {
            get => _selectedCountry;
            set
            {
                _selectedCountry = value;
                OnPropertyChanged();
                UpdateCitiesList();
            }
        }

        private CrCity _selectedCity;
        public CrCity SelectedCity
        {
            get => _selectedCity;
            set
            {
                _selectedCity = value;
                OnPropertyChanged();
            }
        }

        private async void GetCountries()
        {
            // call database here
            var url = string.Concat(Constants.UrlCountry, "?PageSize=", 249);

            var countries = await _apiService.GetCountries(url, CurrentPropertiesService.GetToken());

            Countries = countries.Data;
        }

        private async void UpdateCitiesList()
        {
            var adios = _selectedCountry;

            if(_selectedCountry != null)
            {
                var url = string.Concat(Constants.UrlCity, "?IdCountry=", _selectedCountry.IdCountry,"&PageSize=",120);

                var cities = await _apiService.GetCitiesByCountry(url, CurrentPropertiesService.GetToken());

                Cities = cities.Data;
            }

           
        }

我的查看内容页面上的我的选择器

<StackLayout Grid.Column="0" Grid.Row="3" Orientation="Vertical" HorizontalOptions="Fill">
                        <Label>País:</Label>
                            <Picker x:Name="pickerCountry" Title="Seleccione" 
                                    ItemDisplayBinding="{Binding Country}" 
                                    ItemsSource="{Binding Countries}" 
                                    SelectedItem="{Binding SelectedCountry, Mode=TwoWay}"
                                     />
                    </StackLayout>

                    <StackLayout Grid.Column="0" Grid.Row="4" Orientation="Vertical" HorizontalOptions="Fill">
                        <Label>Ciudad:</Label>
                            <Picker x:Name="pickerCity" Title="Seleccione" 
                                ItemsSource="{Binding Cities}" 
                                ItemDisplayBinding="{Binding City}" 
                                SelectedItem="{Binding SelectedCity, Mode=TwoWay}" >
                                <Picker.Triggers>
                                    <DataTrigger TargetType="Picker" Binding="{Binding Source={x:Reference pickerCountry},Path=SelectedItem}" Value="">
                                        <Setter Property="IsEnabled" Value="False"/>
                                    </DataTrigger>
                                </Picker.Triggers>
                            </Picker>
                    </StackLayout>

请帮助我真的迷失了 MVVM 架构。谢谢。

编辑:

我终于实现了我想要的我用了IsEnabled属性。我按照这个 link:

开始使用 MVVM 有点复杂,但这是我将使用的方法:

Enable/Disable 城市:我会用Xamarin triggers.

您的代码将如下所示:

<StackLayout Grid.Column="0" Grid.Row="3" Orientation="Vertical" HorizontalOptions="Fill">
    <Label>Country:</Label>
    <Picker x:Name="pickerCountry" Title="Select one" ItemDisplayBinding="{Binding Name}" ItemsSource="{Binding Countries}" SelectedIndexChanged="PickerCountry_SelectedIndexChanged" SelectedIndex="{Binding SelectedCountryIndex}"/>
</StackLayout>

<StackLayout Grid.Column="0" Grid.Row="4" Orientation="Vertical" HorizontalOptions="Fill">
    <Label>City:</Label>
    <Picker x:Name="pickerCity" Title="Select one" ItemsSource="{Binding .}" ItemDisplayBinding="{Binding City}" SelectedIndexChanged="PickerCity_SelectedIndexChanged">
        <Picker.Triggers>
             <DataTrigger TargetType="Picker" Binding="{Binding Source={x:Reference pickerCountry},Path=SelectedIndex}" Value="-1">
                 <Setter Property="IsEnabled" Value=False/>
             </DataTrigger>
        </Picker.Triggers>
    </Picker>
</StackLayout>

当所选索引为 -1(即默认值且未选择任何内容)时,它将禁用国家/地区选择器。

更新城市列表

选择国家/地区后,您需要调用数据库以获取所有城市。您需要绑定到 ViewModel 中的 SelectedIndex 或 SelectedItem。在此示例中,我将使用索引:

private int _selectedCountryIndex
public int SelectedCountryIndex
{
    get => _selectedCountryIndex;
    set
    {
        _selectedCountryIndex = value;
        OnPropertyChanged();
        UpdateCitiesList();
    }
}

当国家/地区索引发生变化时,您可以调用 UpdateCititesList() 方法,您可以在其中更新该国家/地区的城市列表

因此,您可能希望在此处查看加载动画,以便用户在检索城市时无法更改国家/地区,或者您可能希望采用不同的策略。稍微考虑一下。