[英]Xamarin.Forms and Prism - How to pass data and navigate to another view?
这是我在这里的第一个问题,大家好。 我正在使用 Prism 开发 Xamarin.Forms 中的移动应用程序。 我创建了 ListView,其中显示了数据库中的数据。
当用户在所选行中单击时,应用程序应导航到新视图并从 ListView 传递所选项目。
<ListView x:Name="DefectsBase"
RowHeight="65"
ItemsSource="{Binding Defects}"
ItemSelected="ShowDetailsEvent"
IsPullToRefreshEnabled="true"
RefreshCommand="{Binding Refresh}"
IsRefreshing="{Binding IsRefreshing}">
代码后端:
async void ShowDetailsEvent(object sender, EventArgs e)
{
var myListView = (ListView)sender;
var myItem = myListView.SelectedItem;
var p = new NavigationParameters();
p.Add("selectedDefect", myItem);
await _navigationService.NavigateAsync("DefectDetailsView", p);
}
不幸的是,应用程序没有响应在 ListView 中按下选定的行。
正如我所看到的,您已经在使用Prism
,并且您有一个包含项目的列表页面,并且您希望根据用户在 ListView 中点击的选定/录制/选择的项目导航到一些详细信息页面。
我们的想法是将尽可能多的代码和逻辑移动到视图 model 并保留我们的代码隐藏。 使用Prism
和EventToCommand
行为很容易解决这个问题。
在下面的示例和答案中,我将向您展示如何用几行代码和一种很好的代码方法来解决这个问题。
首先,我建议您使用EventToCommand
行为,您可以将其包含在 prism xmlns 中,如下所示: xmlns:prism="http://prismlibrary.com"
,稍后您可以将其与 ListView 一起使用。
从 ListView 中删除 ItemSelected 事件并将有关它的标记移动到<ListView.Behaviors>
部分。 这是我绑定到汽车模型的一些ObserverableCollection
的ListView
的代码示例:
<ListView ItemsSource="{Binding Cars}">
<ListView.ItemTemplate>
<DataTemplate>
...
</DataTemplate>
</ListView.ItemTemplate>
<ListView.Behaviors>
<prism:EventToCommandBehavior EventName="ItemTapped"
Command="{Binding SelectedCarCommand}"
EventArgsParameterPath="Item" />
</ListView.Behaviors>
这里的主要部分是<ListView.Behaviors>
,您可以在其中看到我绑定到 SelectedCarCommand ,当用户点击列表中的某些项目时将调用该命令。 我为此使用ItemTapped
事件,并将列表中当前的“录音”项目作为参数传递。
为了在此页面的 model 中遵循此 XAML 部分,我声明了DelegateCommand
和调用命令时将调用的方法。 视图 model 部分如下所示:
这是我的 CarListPageViewModel,看看 DelegateCommand 和 SelectedCar 方法。
public class CarListPageViewModel
{
private readonly INavigationService _navigationService;
public ObservableCollection<Car> Cars { get; set; }
public DelegateCommand<Car> SelectedCarCommand { get; private set; }
public CarListPageViewModel(INavigationService navigationService, IDataProvider dataProvider)
{
_navigationService = navigationService;
// Insert test data into collection of Cars
Cars = new ObservableCollection<Car>(dataProvider.GetData());
SelectedCarCommand = new DelegateCommand<Car>(SelectedCar);
}
private async void SelectedCar(Car selectedCar)
{
NavigationParameters navigationParameters = new NavigationParameters
{
{ "selectedCar", selectedCar }
};
await _navigationService.NavigateAsync(nameof(CarDetailsPage), navigationParameters);
}
}
正如你所看到的,我们定义了DelegateCommand
,参数的类型将被传递,在我的例子中,这是 Car class,与 ListView 中的项目相同的 class。
在构造函数中,我进行了初始化并定义了将要调用的方法,该方法有一个 Car 类型的参数。
当用户点击 ListView 中的一个项目时,将调用 SelectedCar(方法),我们可以使用NavigationParameters
和NavigationService
将数据传递给下一个视图。
为了检索传递的数据,我们可以在详细视图 model 中使用INavigationAware
并使用OnNavigatedTo
方法访问正在传递的数据。
这是我的 CarDetailsPageViewModel,看看OnNavigatedTo
方法。
public class CarDetailsPageViewModel : BindableBase, INavigationAware
{
private string carTitle;
public string CarTitle
{
get { return carTitle; }
set { SetProperty(ref carTitle, value); }
}
private string photoUrl;
public string PhotoUrl
{
get { return photoUrl; }
set { SetProperty(ref photoUrl, value); }
}
public CarDetailsPageViewModel() { }
public void OnNavigatedTo(INavigationParameters parameters)
{
if (parameters.ContainsKey("selectedCar"))
{
Car car = parameters.GetValue<Car>("selectedCar");
if (car != null)
{
CarTitle = $"{car.Make} {car.Model}";
PhotoUrl = car.PhotoUrl;
}
}
}
public void OnNavigatedFrom(INavigationParameters parameters) { }
}
从这个答案和示例中,您可以看到:
EventToCommand
行为与ListView
一起使用DelegateCommand
您可以在我的 GitHub 配置文件中找到代码和此示例。
希望这个答案对你有帮助!
祝你编码好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.