发送 objects 的列表作为导航参数

Send a list of objects as a navigation parameter

我有一个应用程序可以让人们查看有关特定电影的信息。在我的 MainPage (GenreListPage) 中,我有一个列表,将数据库中的每部电影分类为一个流派列表。流派类型和相同流派的电影数量显示在 CollectionView ItemTemplate (GenreModel) 中。当用户点击一个流派时,他们会导航到另一个带有另一个 CollectionView (FilmListPage) 的页面。此 CollectionView 填充有包含电影名称和评级 (FilmModel) 的 ItemTemplate。

目前,当用户导航到 FilmListPage 时,构造函数调用查询数据库的方法,检索在 GenreListPage 中选择的指定类型的所有电影。

我想更改此设置,因此我在我的 GenreModel 中包含了一个 FilmModel 类型的列表。当我导航到 FilmListPage 时,我想将 FilmModel 列表作为参数传递并在 FilmListPage 中检索它。但是根据我的理解,传递导航参数仅意味着传递字符串。这是真的吗?

一些代码;

GenreModel.cs

public class GenreModel{

    public string GenreType {get; set;}

    public List<FilmModel> AssociatedFilms {get; set;}
}

FilmModel.cs

public class FilmModel {

    public string Title {get; set;}

    public double Rating {get; set;}
}

GenreListPageViewModel.cs

public class GenreListPageViewModel.cs  : ViewModelBase
{
    private GenreModel _selectedGenre;
    private List<GenreModel> _genres;

    public GenreModel SelectedGenre 
    {
        get => _selectedGenre;
        set => SetProperty(ref _selectedGenre, value);
    }

    public List<GenreModel> Genres
    {
        get => _genres;
        set => SetProperty(ref _genres, value);
    }

    public GenreListPageViewModel(INavigationService navigationService, IDatabaseService databaseService) : base (navigationService)
    {
        Genres = new ObservableCollection<GenreModel>(databaseService.GetFilms());
    }

    public async void ItemSelected()
    {
        var p = new NavigationParameters;
        p.Add("Films", SelectedGenre.AssociatedFilms);
        p.Add("Genre", SelectedGenre.GenreType);
        await NavigationService.NavigateAsync("FilmListPage", p);
    }
}

FilmListPageViewModel.cs

public class FilmListPageViewModel.cs : ViewModelBase, INavigationAware
{
    IDatabaseService _databaseService;

    private string _genre;
    private List<FilmModel> _films = new List<FilmModel>();

    public string Genre
    {
        get => _genre;
        set => SetProperty(ref _genre, value);
    }

    public List<FilmModel> Films
    {
        get => _films;
        set => SetProperty(ref _films, value);
    }

    public GenreListPageViewModel(INavigationService navigationService, IDatabaseService databaseService) : base (navigationService)
    {
        _databaseService = databaseService;
    }

    public void OnNavigatedFrom(INavigationParameters parameters)
    {

    }

    public void OnNavigatedTo(INavigationParameters parameters)
    {
        Genre = parameters.GetValue<string>("Genre")};

        //old code that used to get film by selected genre
        //Films = databaseService.GetFilmsByGenre(Genre);

        Films = new ObservableCollection<FilmModel>(parameters.GetValues<FilmModel>("Films"));
    }
}

However from my understanding passing navigation parameters only means passing strings. Is this true?

幸运的是,不,与键关联的值可以是任何东西(看看 the code):

public interface INavigationParameters : IEnumerable<KeyValuePair<string, object>>

导航和对话框参数实际上都是IEnumerable<KeyValuePair<string, object>>。那么这对您意味着什么?

对于初学者来说,这意味着任何给定的键都可能包含一对多的实际值。

navigationParameters.Add("message", "Prism is great for Wpf apps");
navigationParameters.Add("message", "Prism is great for Xamarin.Forms apps");
navigationParameters.Add("message", "Prism is great for Uno and WinUI apps");

其次,这意味着你可以传递任何你想要的作为参数。

var messages = new[] {
    "Prism is great for Wpf apps",
    "Prism is great for Xamarin.Forms apps",
    "Prism is great for Uno and WinUI apps"
};
navigationParameters.Add("message", messages);

正如您可能熟悉的那样,您可以像这样提取参数:

var messages = navigationParameters.Get<IEnumerable<string>>("message");

如果您使用添加消息的第一种方式使用此方法,您可能会遇到异常,因为它会命中第一个值并发现它不是同一类型。如果您以第二种方式添加它,这仍然有效,因为您添加了一个 IEnumerable<string>.

然而,还有第二种方法非常适合您要查找的内容,并且无论您的值是如何添加的,都可以使用。

var messages = navigationParameters.GetValues<string>("message");

GetValues 方法 returns 给定泛型的 IEnumerable。