Xamarin - 将选择器绑定到 MVVM 命令
Xamarin - Binding a Picker to MVVM command
我正在尝试在我的 Xamarin 项目中使用 MVVM 架构,但我还不太理解它。
我有两个实体 CrCountry
和 CrCity
,我希望用户能够选择一个国家,然后根据该国家 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() 方法,您可以在其中更新该国家/地区的城市列表
因此,您可能希望在此处查看加载动画,以便用户在检索城市时无法更改国家/地区,或者您可能希望采用不同的策略。稍微考虑一下。
我正在尝试在我的 Xamarin 项目中使用 MVVM 架构,但我还不太理解它。
我有两个实体 CrCountry
和 CrCity
,我希望用户能够选择一个国家,然后根据该国家 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() 方法,您可以在其中更新该国家/地区的城市列表
因此,您可能希望在此处查看加载动画,以便用户在检索城市时无法更改国家/地区,或者您可能希望采用不同的策略。稍微考虑一下。