RUDE

Xamarin — привязка средства выбора к команде MVVM

Я пытаюсь использовать архитектуру MVVM в своем проекте Xamarin, но пока не могу ее понять.

У меня есть две сущности CrCountry и CrCity, и я хочу, чтобы пользователь мог выбрать страну, а затем на основе этой страны выбрать город. Я также хочу, чтобы средство выбора города было «недоступным», пока пользователь не выберет страну.

Для этого мне нужно знать элемент, выбранный в моем средстве выбора, чтобы я мог получить доступ к своей базе данных и передать это значение. Как я могу это сделать?

Обновлено:

Теперь он работает с тем, что у меня есть, единственное, что не работает, — это свойство IsEnabled в моем средстве выбора города. Как я уже сказал, я хочу, чтобы средство выбора города было отключено, пока не будет выбрана страна. Я не могу использовать SelectedIndex вместо SelectedItem, так как мой объект CrCountry имеет строку в качестве идентификатора, и мне нужно получить выбранный элемент для фильтрации городов по стране. Вот что у меня есть:

Моя модель представления

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. Я перешел по этой ссылке: Как отключить DatePicker из модели представления WPF MVVM


37
1

Ответ:

Решено

Немного сложно начать работу с MVVM, но вот подход, который я бы использовал:

Включить/отключить города: я бы использовал Триггеры Xamarin.

Ваш код будет выглядеть примерно так:

<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 (т. е. значение по умолчанию и ничего не выбрано), он отключит средство выбора стран.

Обновить список городов

После того, как страна выбрана, вы хотите вызвать в свою базу данных, чтобы получить все города. Вы захотите привязаться к SelectedIndex или SelectedItem в своей ViewModel. В этом примере я буду использовать индекс:

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

Когда индекс страны изменяется, вы вызываете метод UpdateCititesList(), где вы можете обновить список городов в этой стране.

Таким образом, вы можете рассмотреть анимацию загрузки здесь, чтобы пользователи не могли изменить страну, пока вы извлекаете города, или вы можете использовать другую стратегию. Просто подумайте об этом немного.