Xamarin.Forms 和 Prism - 如何传递数据并导航到另一个视图?

Xamarin.Forms and Prism - How to pass data and navigate to another view?

这是我的第一个问题,大家好。 我正在 Xamarin.Forms 中使用 Prism 开发移动应用程序。我创建了 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 并且您有一个包含项目的列表页面,并且您希望根据用户在列表视图。

我们的想法是将尽可能多的代码和逻辑移动到视图模型并保持我们的代码隐藏。使用 PrismEventToCommand 行为很容易解决。

在下面的示例和答案中,我将向您展示如何用几行代码和一个很好的代码方法来解决这个问题。

首先,我推荐你使用EventToCommand行为,你可以将它包含在prism xmlns中,像这样:xmlns:prism="http://prismlibrary.com",稍后,你可以将它与ListView一起使用。

从您的 ListView 中删除 ItemSelected 事件,并将关于它的标记移动到 <ListView.Behaviors> 部分。这是我的 ListView 代码示例,它绑定到某些 ObserverableCollection 汽车型号:

<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 事件,并将列表中的当前“taped”项目作为参数传递。

为了在本页的视图模型中遵循此 XAML 部分,我声明了 DelegateCommand 和调用命令时将调用的方法。视图模型部分如下所示:

这是我的 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,与我们的 class 相同ListView 中的项目。

在构造函数中,我进行了初始化并定义了将要调用的方法,该方法有一个 Car 类型的参数。

当用户点击 ListView 中的一项时,将调用 SelectedCar(方法),我们可以使用 NavigationParametersNavigationService 将数据传递到下一个视图。

为了检索传递的数据,我们可以在详细信息视图模型中使用 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 个人资料 here.

上找到代码和示例

希望这个回答对您有所帮助!

祝您编码顺利!