欧美日韩亚-欧美日韩亚州在线-欧美日韩亚洲-欧美日韩亚洲第一区-欧美日韩亚洲二区在线-欧美日韩亚洲高清精品

金喜正规买球

Xamarin Forms的Prism第二部分:基本導航和依賴注入(Dependency Injection)模式

原創|使用教程|編輯:黃竹雯|2016-09-18 18:01:27.000|閱讀 1777 次

概述:本系列的第2部分展示了Prism如何在一個MVVM應用程序中啟動導航。

# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>

相關鏈接:

前一篇文章中,我們已經開始介紹在Xamarin Forms應用程序中如何利用Prism(6.2)的新版本來實現MVVM模式的基本概念。到目前為止,我們還沒有看到什么特別的東西是我們用另一個框架做不到的:我們在上一篇文章中創建了一個視圖(View)、一個視圖模型(ViewModel),然后我們通過綁定連接它們。在這篇文章中,我們將看到Prism如何幫助處理一個在MVVM應用程序中很難處理的非常常見的場景:導航和頁面的生命周期。

Xamarin Forms的Prism第二部分:基本導航和依賴注入(Dependency Injection)模式

正如我們在前一篇文章中提到的,我們要為TrackSeries——一個提供電視節目信息的網站,創建一個簡單的客戶端。該應用程序將顯示當前的頂級系列,將允許用戶發現更多關于它的內容。為了實現這一目標,我們可以用一組網站提供的REST服務,這是非常簡單的使用和處理REST服務的遵循標準的最佳實踐:你調用一個使用HTTP命令的URL,接收返回一個JSON響應結果。

舉個例子,如果你想知道哪些是頂級系列,你可以執行一個HTTP GET請求到以下URL:。服務將返回給你一個JSON響應,包含頂級系列的所有細節:

[
   {
      "id":121361,
      "name":"Game of Thrones",
      "followers":10230,
      "firstAired":"2011-04-17T21:00:00-04:00",
      "country":"us",
      "overview":"Seven noble families fight for control of the mythical land of Westeros. Friction between the houses leads to full-scale war. All while a very ancient evil awakens in the farthest north. Amidst the war, a neglected military order of misfits, the Night's Watch, is all that stands between the realms of men and the icy horrors beyond.",
      "runtime":55,
      "status":"Continuing",
      "network":"HBO",
      "airDay":"Sunday",
      "airTime":"9:00 PM",
      "contentRating":"TV-MA",
      "imdbId":"tt0944947",
      "tvdbId":121361,
      "tmdbId":1399,
      "language":"en",
      "images":{
         "poster":"//static.trackseries.tv/banners/posters/121361-49.jpg",
         "fanart":"//static.trackseries.tv/banners/fanart/original/121361-15.jpg",
         "banner":"//static.trackseries.tv/banners/graphical/121361-g22.jpg"
      },
      "genres":[
         {
            "id":2,
            "name":"Adventure"
         },
         {
            "id":4,
            "name":"Drama"
         },
         {
            "id":5,
            "name":"Fantasy"
         }
      ],
      "added":"2014-08-08T13:30:46.227",
      "lastUpdated":"2016-08-18T03:03:50.05",
      "followedByUser":false,
      "slugName":"game-of-thrones"
   },
   {
      "id":257655,
      "name":"Arrow",
      "followers":7517,
      "firstAired":"2012-10-10T20:00:00-04:00",
      "country":"us",
      "overview":"Oliver Queen and his father are lost at sea when their luxury yacht sinks. His father doesn't survive. Oliver survives on an uncharted island for five years learning to fight, but also learning about his father's corruption and unscrupulous business dealings. He returns to civilization a changed man, determined to put things right. He disguises himself with the hood of one of his mysterious island mentors, arms himself with a bow and sets about hunting down the men and women who have corrupted his city.",
      "runtime":45,
      "status":"Continuing",
      "network":"The CW",
      "airDay":"Wednesday",
      "airTime":"8:00 PM",
      "contentRating":"TV-14",
      "imdbId":"tt2193021",
      "tvdbId":257655,
      "tmdbId":1412,
      "language":"en",
      "images":{
         "poster":"//static.trackseries.tv/banners/posters/257655-8.jpg",
         "fanart":"//static.trackseries.tv/banners/fanart/original/257655-47.jpg",
         "banner":"//static.trackseries.tv/banners/graphical/257655-g9.jpg"
      },
      "genres":[
         {
            "id":1,
            "name":"Action"
         },
         {
            "id":2,
            "name":"Adventure"
         },
         {
            "id":4,
            "name":"Drama"
         }
      ],
      "added":"2014-08-08T13:37:00.133",
      "lastUpdated":"2016-08-15T03:11:32.013",
      "followedByUser":false,
      "slugName":"arrow"
   },
   {
      "id":153021,
      "name":"The Walking Dead",
      "followers":7185,
      "firstAired":"2010-10-31T21:00:00-04:00",
      "country":"us",
      "overview":"The world we knew is gone. An epidemic of apocalyptic proportions has swept the globe causing the dead to rise and feed on the living. In a matter of months society has crumbled. In a world ruled by the dead, we are forced to finally start living. Based on a comic book series of the same name by Robert Kirkman, this AMC project focuses on the world after a zombie apocalypse. The series follows a police officer, Rick Grimes, who wakes up from a coma to find the world ravaged with zombies. Looking for his family, he and a group of survivors attempt to battle against the zombies in order to stay alive.\n",
      "runtime":50,
      "status":"Continuing",
      "network":"AMC",
      "airDay":"Sunday",
      "airTime":"9:00 PM",
      "contentRating":"TV-MA",
      "imdbId":"tt1520211",
      "tvdbId":153021,
      "tmdbId":1402,
      "language":"en",
      "images":{
         "poster":"//static.trackseries.tv/banners/posters/153021-38.jpg",
         "fanart":"//static.trackseries.tv/banners/fanart/original/153021-77.jpg",
         "banner":"//static.trackseries.tv/banners/graphical/153021-g44.jpg"
      },
      "genres":[
         {
            "id":1,
            "name":"Action"
         },
         {
            "id":4,
            "name":"Drama"
         },
         {
            "id":6,
            "name":"Horror"
         },
         {
            "id":20,
            "name":"Suspense"
         }
      ],
      "added":"2014-08-08T13:31:18.617",
      "lastUpdated":"2016-08-18T03:04:00.28",
      "followedByUser":false,
      "slugName":"the-walking-dead"
   },
   {
      "id":279121,
      "name":"The Flash (2014)",
      "followers":7069,
      "firstAired":"2014-10-07T20:00:00-04:00",
      "country":"us",
      "overview":"After a particle accelerator causes a freak storm, CSI Investigator Barry Allen is struck by lightning and falls into a coma. Months later he awakens with the power of super speed, granting him the ability to move through Central City like an unseen guardian angel. Though initially excited by his newfound powers, Barry is shocked to discover he is not the only \"meta-human\" who was created in the wake of the accelerator explosion – and not everyone is using their new powers for good. Barry partners with S.T.A.R. Labs and dedicates his life to protect the innocent. For now, only a few close friends and associates know that Barry is literally the fastest man alive, but it won't be long before the world learns what Barry Allen has become... The Flash.",
      "runtime":45,
      "status":"Continuing",
      "network":"The CW",
      "airDay":"Tuesday",
      "airTime":"8:00 PM",
      "contentRating":"TV-14",
      "imdbId":"tt3107288",
      "tvdbId":279121,
      "tmdbId":60735,
      "language":"en",
      "images":{
         "poster":"//static.trackseries.tv/banners/posters/279121-37.jpg",
         "fanart":"//static.trackseries.tv/banners/fanart/original/279121-23.jpg",
         "banner":"//static.trackseries.tv/banners/graphical/279121-g7.jpg"
      },
      "genres":[
         {
            "id":1,
            "name":"Action"
         },
         {
            "id":2,
            "name":"Adventure"
         },
         {
            "id":4,
            "name":"Drama"
         },
         {
            "id":8,
            "name":"Science-Fiction"
         }
      ],
      "added":"2014-08-08T13:45:59.087",
      "lastUpdated":"2016-08-17T03:09:18.7",
      "followedByUser":false,
      "slugName":"the-flash-2014"
   },
   {
      "id":80379,
      "name":"The Big Bang Theory",
      "followers":6922,
      "firstAired":"2007-09-25T20:00:00-04:00",
      "country":"us",
      "overview":"What happens when hyperintelligent roommates Sheldon and Leonard meet Penny, a free-spirited beauty moving in next door, and realize they know next to nothing about life outside of the lab. Rounding out the crew are the smarmy Wolowitz, who thinks he's as sexy as he is brainy, and Koothrappali, who suffers from an inability to speak in the presence of a woman.",
      "runtime":25,
      "status":"Continuing",
      "network":"CBS",
      "airDay":"Monday",
      "airTime":"8:00 PM",
      "contentRating":"TV-PG",
      "imdbId":"tt0898266",
      "tvdbId":80379,
      "tmdbId":1418,
      "language":"en",
      "images":{
         "poster":"//static.trackseries.tv/banners/posters/80379-43.jpg",
         "fanart":"//static.trackseries.tv/banners/fanart/original/80379-38.jpg",
         "banner":"//static.trackseries.tv/banners/graphical/80379-g28.jpg"
      },
      "genres":[
         {
            "id":3,
            "name":"Comedy"
         }
      ],
      "added":"2014-08-08T13:27:13.18",
      "lastUpdated":"2016-08-18T03:03:10.947",
      "followedByUser":false,
      "slugName":"the-big-bang-theory"
   },
   {
      "id":176941,
      "name":"Sherlock",
      "followers":6387,
      "firstAired":"2010-07-25T20:30:00+01:00",
      "country":"gb",
      "overview":"Sherlock is a British television crime drama that presents a contemporary adaptation of Sir Arthur Conan Doyle's Sherlock Holmes detective stories. Created by Steven Moffat and Mark Gatiss, it stars Benedict Cumberbatch as Sherlock Holmes and Martin Freeman as Doctor John Watson.",
      "runtime":90,
      "status":"Continuing",
      "network":"BBC One",
      "airDay":"Sunday",
      "airTime":"8:30 PM",
      "contentRating":"TV-14",
      "imdbId":"tt1475582",
      "tvdbId":176941,
      "tmdbId":19885,
      "language":"en",
      "images":{
         "poster":"//static.trackseries.tv/banners/posters/176941-11.jpg",
         "fanart":"//static.trackseries.tv/banners/fanart/original/176941-3.jpg",
         "banner":"//static.trackseries.tv/banners/graphical/176941-g5.jpg"
      },
      "genres":[
         {
            "id":2,
            "name":"Adventure"
         },
         {
            "id":4,
            "name":"Drama"
         },
         {
            "id":14,
            "name":"Crime"
         },
         {
            "id":16,
            "name":"Mystery"
         },
         {
            "id":21,
            "name":"Thriller"
         }
      ],
      "added":"2014-08-08T13:32:27.247",
      "lastUpdated":"2016-08-17T03:07:09.747",
      "followedByUser":false,
      "slugName":"sherlock"
   },
   {
      "id":263365,
      "name":"Marvel's Agents of S.H.I.E.L.D.",
      "followers":5372,
      "firstAired":"2013-09-24T22:00:00-04:00",
      "country":"us",
      "overview":"Phil Coulson (Clark Gregg, reprising his role from \"The Avengers\" and \"Iron Man\" ) heads an elite team of fellow agents with the worldwide law-enforcement organization known as SHIELD (Strategic Homeland Intervention Enforcement and Logistics Division), as they investigate strange occurrences around the globe. Its members -- each of whom brings a specialty to the group -- work with Coulson to protect those who cannot protect themselves from extraordinary and inconceivable threats, including a formidable group known as Hydra.",
      "runtime":45,
      "status":"Continuing",
      "network":"ABC (US)",
      "airDay":"Tuesday",
      "airTime":"10:00 PM",
      "contentRating":"TV-PG",
      "imdbId":"tt2364582",
      "tvdbId":263365,
      "tmdbId":1403,
      "language":"en",
      "images":{
         "poster":"//static.trackseries.tv/banners/posters/263365-16.jpg",
         "fanart":"//static.trackseries.tv/banners/fanart/original/263365-26.jpg",
         "banner":"//static.trackseries.tv/banners/graphical/263365-g7.jpg"
      },
      "genres":[
         {
            "id":1,
            "name":"Action"
         },
         {
            "id":2,
            "name":"Adventure"
         },
         {
            "id":4,
            "name":"Drama"
         },
         {
            "id":5,
            "name":"Fantasy"
         },
         {
            "id":8,
            "name":"Science-Fiction"
         }
      ],
      "added":"2014-08-08T13:39:45.967",
      "lastUpdated":"2016-08-18T03:05:30.987",
      "followedByUser":false,
      "slugName":"marvels-agents-of-shield"
   },
   {
      "id":81189,
      "name":"Breaking Bad",
      "followers":5227,
      "firstAired":"2008-01-20T21:00:00-04:00",
      "country":"us",
      "overview":"Walter White, a struggling high school chemistry teacher, is diagnosed with advanced lung cancer. He turns to a life of crime, producing and selling methamphetamine accompanied by a former student, Jesse Pinkman, with the aim of securing his family's financial future before he dies.",
      "runtime":45,
      "status":"Ended",
      "network":"AMC",
      "airDay":"Sunday",
      "airTime":"9:00 PM",
      "contentRating":"TV-MA",
      "imdbId":"tt0903747",
      "tvdbId":81189,
      "tmdbId":1396,
      "language":"en",
      "images":{
         "poster":"//static.trackseries.tv/banners/posters/81189-10.jpg",
         "fanart":"//static.trackseries.tv/banners/fanart/original/81189-21.jpg",
         "banner":"//static.trackseries.tv/banners/graphical/81189-g21.jpg"
      },
      "genres":[
         {
            "id":4,
            "name":"Drama"
         },
         {
            "id":14,
            "name":"Crime"
         },
         {
            "id":20,
            "name":"Suspense"
         },
         {
            "id":21,
            "name":"Thriller"
         }
      ],
      "added":"2014-08-08T13:27:33.917",
      "lastUpdated":"2016-08-13T03:01:47.063",
      "followedByUser":false,
      "slugName":"breaking-bad"
   },
   {
      "id":247808,
      "name":"Suits",
      "followers":4835,
      "firstAired":"2011-06-24T21:00:00-04:00",
      "country":"us",
      "overview":"Suits follows college drop-out Mike Ross, who accidentally lands a job with one of New York's best legal closers, Harvey Specter. They soon become a winning team with Mike's raw talent and photographic memory, and Mike soon reminds Harvey of why he went into the field of law in the first place.",
      "runtime":45,
      "status":"Continuing",
      "network":"USA Network",
      "airDay":"Wednesday",
      "airTime":"9:00 PM",
      "contentRating":"TV-14",
      "imdbId":"tt1632701",
      "tvdbId":247808,
      "tmdbId":37680,
      "language":"en",
      "images":{
         "poster":"//static.trackseries.tv/banners/posters/247808-27.jpg",
         "fanart":"//static.trackseries.tv/banners/fanart/original/247808-43.jpg",
         "banner":"//static.trackseries.tv/banners/graphical/247808-g17.jpg"
      },
      "genres":[
         {
            "id":4,
            "name":"Drama"
         }
      ],
      "added":"2014-08-08T13:33:45.423",
      "lastUpdated":"2016-08-18T03:04:21.37",
      "followedByUser":false,
      "slugName":"suits"
   },
   {
      "id":274431,
      "name":"Gotham",
      "followers":4718,
      "firstAired":"2014-09-23T20:00:00-04:00",
      "country":"us",
      "overview":"An action-drama series following rookie detective James Gordon as he battles villains and corruption in pre-Batman Gotham City.",
      "runtime":45,
      "status":"Continuing",
      "network":"FOX (US)",
      "airDay":"Monday",
      "airTime":"8:00 PM",
      "contentRating":"TV-14",
      "imdbId":"tt3749900",
      "tvdbId":274431,
      "tmdbId":60708,
      "language":"en",
      "images":{
         "poster":"//static.trackseries.tv/banners/posters/274431-17.jpg",
         "fanart":"//static.trackseries.tv/banners/fanart/original/274431-22.jpg",
         "banner":"//static.trackseries.tv/banners/graphical/274431-g6.jpg"
      },
      "genres":[
         {
            "id":1,
            "name":"Action"
         },
         {
            "id":4,
            "name":"Drama"
         },
         {
            "id":8,
            "name":"Science-Fiction"
         },
         {
            "id":14,
            "name":"Crime"
         },
         {
            "id":21,
            "name":"Thriller"
         }
      ],
      "added":"2014-08-08T13:44:55.4",
      "lastUpdated":"2016-08-17T03:08:55.473",
      "followedByUser":false,
      "slugName":"gotham"
   }
]

為了使用這些應用程序中的API,我用一組方法創建了一個稱為TsApiService的類,通過.NET框架和流行的JSON.NET庫的HttpClient類,負責下載JSON,解析它并返回一組可以使用C#很容易地操縱的對象。為了更好地構成我的解決方案, 我已經決定把所有的通信相關類與REST API (如服務和實體)放置在另一個叫做InfoSeries.Core的便攜式類庫(Portable Class Library)中,這是一個與實際Xamarin Forms應用程序的相比不同的PCL。

這就是負責解析之前的JSON的方法返回一個C#對象列表:

public async Task<List<SerieFollowersVM>> GetStatsTopSeries()
{
    using (HttpClient client = new HttpClient())
    {
        try
        {
            var response = await client.GetAsync("//api.trackseries.tv/v1/Stats/TopSeries");
            if (!response.IsSuccessStatusCode)
            {
                var error = await response.Content.ReadAsAsync<TrackSeriesApiError>();
                var message = error != null ? error.Message : "";
                throw new TrackSeriesApiException(message, response.StatusCode);
            }
            return await response.Content.ReadAsAsync<List<SerieFollowersVM>>();
        }
        catch (HttpRequestException ex)
        {
            throw new TrackSeriesApiException("", false, ex);
        }
        catch (UnsupportedMediaTypeException ex)
        {
            throw new TrackSeriesApiException("", false, ex);
        }
    }
}

HttpClient類的GetAsync() 方法執行GET請求到URL,返回結果包含JSON響應的字符串。這個結果存儲在響應的Content 屬性:如果請求成功(我們使用IsSuccessStatusCode 屬性檢查這種情況),我們使用Content 屬性公開的ReadAsAsync< T >方法自動轉換為JSON導致SerieFollowersVM 對象的集合。SerieFollowersVM 無非是一個映射JSON響應的每個屬性的類 (如namecountryruntime)到一個C#屬性:

public class SerieFollowersVM
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Followers { get; set; }
    public DateTimeOffset FirstAired { get; set; }
    public string Country { get; set; }
    public string Overview { get; set; }
    public int Runtime { get; set; }
    public string Status { get; set; }
    public string Network { get; set; }
    public DayOfWeek? AirDay { get; set; }
    public string AirTime { get; set; }
    public string ContentRating { get; set; }
    public string ImdbId { get; set; }
    public int TvdbId { get; set; }
    public string Language { get; set; }
    public ImagesSerieVM Images { get; set; }
    public ICollection<GenreVM> Genres { get; set; }
    public DateTime Added { get; set; }
    public DateTime LastUpdated { get; set; }
    public string SlugName { get; set; }
}

在GitHub的完整示例(為了方便各位讀者,小編已經為大家整理了,請點擊這里下載)中你會發現很多這樣的類(映射各種被TrackSeries API返回的JSON響應)。此外,TsApiService 將實現另外的方法,一個用于我們想在我們的應用程序中利用的每個API的方法。我不會詳細解釋每個方法,因為這將超出本文的范圍,你可以在GitHub上看到所有的細節。對于這篇文章的目的,你只需要知道服務只是公開了一組方法,我們可以在各種ViewModels中使用來檢索可用的電視節目的信息。

注意:默認情況下,HttpClient 類沒有提供一個ReadAsAsync< T >方法,能夠自動對JSON響應為C#對象進行反序列化。為了獲得該擴展方法,我們需要添加Microsoft.AspNet.WebApi.Client NuGet包到便攜類庫(Portable Class Library)。為了讓它正常工作,你需要將這個包添加到解決方案的每個項目(Xamarin Forms PCL、Core PCL和所有特定于平臺的項目)。

然而,為了正確利用依賴注入(dependency injection),我們需要一個接口來描述TsApiService 類提供的操作。這就是我們的接口的樣子:

public interface ITsApiService
{
    Task<List<SerieFollowersVM>> GetStatsTopSeries();
    Task<SerieVM> GetSerieByIdAll(int id);
    Task<SerieInfoVM> GetSerieById(int id);
    Task<List<SerieSearch>> GetSeriesSearch(string name);
    Task<SerieFollowersVM> GetStatsSerieHighlighted();
}

現在我們有了一個服務,我們可以學習(多虧Prism)我們可以如何注冊到它的依賴容器,它會自動注入在我們的ViewModels。實際上,從這個角度來看,沒有什么特別強調:這與其他MVVM框架使用的方法是相同的,利用依賴注入的方法。首先,我們需要注冊我們想要在容器中使用的接口和實現之間的協會。在Prism的情況下,我們需要用App類的RegisterTypes()方法,通過使用Container對象和RegisterType< T, Y >()方法(其中T 是接口,Y是具體實現):

protected override void RegisterTypes()
{
    Container.RegisterTypeForNavigation<MainPage>();
    Container.RegisterType<ITsApiService, TsApiService>();
}

MainPage TsApiService 都在容器注冊了,我們可以在ViewModel獲得它,只需添加一個參數在公共構造函數,就像以下示例:

public class MainPageViewModel : BindableBase
{
    private readonly ITsApiService _apiService;
    public MainPageViewModel(ITsApiService apiService)
    {
        _apiService = apiService;
    }
}

MainPageViewModel 類將被加載時,我們已經在容器注冊的ITsApiService實現(在我們的例子中是TsApiService 類)將自動注入構造函數的參數,允許我們以我們將在ViewModel創建的所有其他的方法和屬性來使用它。使用這種方法,我們將容易改變服務的實現,以防我們需要它:它將足以改變App類的注冊類型,并且每個ViewModel將自動開始使用新的版本。

處理導航的生命周期

現在我們有一個服務,它提供了一種方法來檢索頂級系列的列表,在ViewModel加載時我們需要調用它。我們的目標是顯示(在應用程序的主頁)最熱門的電視節目列表。但是,我們即將面對使用MVVM模式時的一個常見的問題:檢索頂級系列列表的方法是異步的,但是隨著當前實現,唯一我們可以執行數據加載的地方就是ViewModel的構造函數,它不能執行異步調用(在C#中,事實上,一個類的構造函數不能用async關鍵字,因此,你不能用等待前綴的方法)。在non-MVVM應用程序中,這個問題很容易解決,因為導航的生命周期方法是由每一個平臺基本提供的。Xamarin Forms毫無例外,我們可以利用(在XAML頁面類的后面的代碼)OnAppearing()OnDisappearing()方法:因為它們是事件,我們可以沒有問題地調用異步代碼。

為了解決這個問題,Prism提供一個稱為INavigationAware的接口,我們可以在ViewModels實現。當我們實現它,我們可以訪問OnNavigatedTo()OnNavigatedFrom()事件,我們可以使用它們來執行數據加載或清理操作。這就是實現這個接口后我們的MainPageViewModel 的樣子:

public class MainPageViewModel : BindableBase, INavigationAware
{
    private readonly TsApiService _apiService;
    private ObservableCollection<SerieFollowersVM> _topSeries;
    public ObservableCollection<SerieFollowersVM> TopSeries
    {
        get { return _topSeries; }
        set { SetProperty(ref _topSeries, value); }
    }
    public MainPageViewModel(TsApiService apiService)
    {
        _apiService = apiService;
    }
    public void OnNavigatedFrom(NavigationParameters parameters)
    {
    }
    public async void OnNavigatedTo(NavigationParameters parameters)
    {
        var result = await _apiService.GetStatsTopSeries();
        TopSeries = new ObservableCollection<SerieFollowersVM>(result);
    }
}

正如你所看到的,現在我們實現了一個稱為OnNavigatedTo()的方法,我們可以安全地執行異步調用和加載數據。我們調用TsApiService類的GetStatsTopSeries()方法,我們封裝結果集合到ObservableCollection屬性。這是我們要連接的屬性,通過綁定到一個ListView 控件,為了在主頁顯示電視節目列表。

出于完整性的考慮,這是MainPage的XAML的樣子:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="//xamarin.com/schemas/2014/forms"
             xmlns:x="//schemas.microsoft.com/winfx/2009/xaml"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="InfoSeries.Views.MainPage"
             Title="Info Series">
  <ContentPage.Resources>
    <ResourceDictionary>
      <DataTemplate x:Key="TopSeriesTemplate">
        <ViewCell>
          <ViewCell.View>
            <Grid>
              <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*" />
                <ColumnDefinition Width="2*" />
              </Grid.ColumnDefinitions>
              <Image Source="{Binding Images.Poster}" Grid.Column="0" x:Name="TopImage" />
              <StackLayout Grid.Column="1" Margin="12, 0, 0, 0" VerticalOptions="Start">
                <Label Text="{Binding Name}" FontSize="18" TextColor="#58666e" FontAttributes="Bold" />
                <StackLayout Orientation="Horizontal">
                  <Label Text="Runtime: " FontSize="14" TextColor="#58666e" />
                  <Label Text="{Binding Runtime}" FontSize="14" TextColor="#98a6ad" Margin="5, 0, 0, 0" />
                </StackLayout>
                <StackLayout Orientation="Horizontal">
                  <Label Text="Air day: " FontSize="14" TextColor="#58666e" />
                  <Label Text="{Binding AirDay}" FontSize="14" TextColor="#98a6ad" Margin="5, 0, 0, 0" />
                </StackLayout>
                <StackLayout Orientation="Horizontal">
                  <Label Text="Country: " FontSize="14" TextColor="#58666e" />
                  <Label Text="{Binding Country}" FontSize="14" TextColor="#98a6ad" Margin="5, 0, 0, 0" />
                </StackLayout>
                <StackLayout Orientation="Horizontal">
                  <Label Text="Network: " FontSize="14" TextColor="#58666e" />
                  <Label Text="{Binding Network}" FontSize="14" TextColor="#98a6ad" Margin="5, 0, 0, 0" />
                </StackLayout>
              </StackLayout>
            </Grid>
          </ViewCell.View>
        </ViewCell>
      </DataTemplate>
    </ResourceDictionary>
  </ContentPage.Resources>
  <ListView ItemTemplate="{StaticResource TopSeriesTemplate}"
            ItemsSource="{Binding Path=TopSeries}" RowHeight="200"/>
</ContentPage>

如果你已經知道Xamarin Forms(或一般的XAML),你應該會覺得這段代碼很容易理解:頁面包含一個ListView 控件、一個描述單個電視節目的模板。我們展示節目的海報,還有一些其他信息,如標題、運行時、生產國家等等。因為(根據命名約定)MainPageViewModel 類已經設置為頁面的BindingContext ,我們可以通過綁定ListViewItemsSource屬性和我們之前在ViewModel填充的TopSeries集合進行簡單地連接。

導航與參數

我們已經看到了如何利用OnNavigatedTo()方法來執行數據加載,但通常這種方法在另一個場景中也是有用的:檢索參數通過前一頁,這通常需要了解當前的上下文(在我們的示例中,在我們的應用程序的詳細信息頁面,我們需要理解用戶已經選擇的電視節目)。

Prism支持這個特性是由于一個稱為NavigationParameters的類稱,可以作為NavigationServiceNavigationAsync()方法的一個可選參數傳遞,它被自動包括作為OnNavigatedTo()OnNavigatedFrom()事件的參數。讓我們看看如何通過向我們的應用程序添加詳細信息頁面利用這個特性,顯示選擇的節目的一些額外的信息。

第一步是同時添加一個新頁面到Views 文件夾中(稱為DetailPage.xaml)和一個新類到ViewModels文件夾中(稱為DetailPageViewModel.cs)。你需要記住,每一頁都需要在App類的容器中注冊,在OnRegisterTypes()方法內:

protected override void RegisterTypes()
{
    Container.RegisterTypeForNavigation<MainPage>();
    Container.RegisterTypeForNavigation<DetailPage>();
    Container.RegisterType<ITsApiService, TsApiService>();
}

由于命名約定,我們不需要做任何特別的操作:新頁面和新ViewModel已經連接。現在我們需要通過ListView控件中所選條目到新頁面。讓我們先看看如何在主頁處理選擇。通過使用由我親愛的朋友Corrado Cavalli創建的庫,我們會得到一些幫助,它允許你在Xamarin Forms應用程序實現行為。可用的行為中的EventToCommand允許我們連接暴露于控件的任何事件與ViewModel中定義的命令。我們要用它來連接ListView 控件的ItemTapped 事件(當用戶點擊列表中的一個項目時會觸發)與我們要在MainPageViewModel中創建來觸發導航到詳細頁面的命令。

你可以從NuGet安裝由Corrado創建的套包,它的名字叫Corcav.Behaviors。使用它你需要添加一個額外的名稱空間到MainPage的root,像下面這個示例:

<ContentPage xmlns="//xamarin.com/schemas/2014/forms"
             xmlns:x="//schemas.microsoft.com/winfx/2009/xaml"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             xmlns:behaviors="clr-namespace:Corcav.Behaviors;assembly=Corcav.Behaviors"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="InfoSeries.Views.MainPage"
             Title="Info Series">
    ...
</ContentPage>

然后你可以申請ListView 控件的行為,就像你在普通Windows應用程序中會做的一樣:

<ListView ItemTemplate="{StaticResource TopSeriesTemplate}"
          ItemsSource="{Binding Path=TopSeries}" RowHeight="200">
  <behaviors:Interaction.Behaviors>
    <behaviors:BehaviorCollection>
      <behaviors:EventToCommand EventName="ItemTapped" Command="{Binding GoToDetailPage}" />
    </behaviors:BehaviorCollection>
  </behaviors:Interaction.Behaviors>
</ListView>

由于這種行為,我們已經連接了ListView 控件的ItemTapped 事件與我們要在ViewModel定義的稱為GoToDetailPage 的命令。從一個框架的角度,Prism沒有做任何不尋常的事幫助開發者實現命令:它只是提供了一個稱為DelegateCommand的類,這允許你定義操作來執行調用命令和可選的條件來啟動命令。如果你有一些MVVM Light以往的經驗,它會以RelayCommand 類那樣完全相同的方式運作。以下是我們的命令在MainPageViewModel 類的樣子:

private DelegateCommand<ItemTappedEventArgs> _goToDetailPage;
public DelegateCommand<ItemTappedEventArgs> GoToDetailPage
{
    get
    {
        if (_goToDetailPage == null)
        {
            _goToDetailPage = new DelegateCommand<ItemTappedEventArgs>(async selected =>
            {
                NavigationParameters param = new NavigationParameters();
                param.Add("show", selected.Item);
                await _navigationService.NavigateAsync("DetailPage", param);
            });
        }
        return _goToDetailPage;
    }
}

我們已經創建了的命令是一個參數化命令;事實上,屬性類型是DelegateCommand< ItemTappedEventArgs >:這種方式,在方法內部,我們獲得存儲在Item 屬性中的選中的條目。命令觸發時調用的方法展示了如何用參數的工作原理導航:首先我們創建一個新的NavigationParameters對象,最后,只不過是一個你可以存儲鍵/值對的字典。因此,我們只需添加一個新項,作為關鍵,關鍵字show ,作為值,選中的項的類型是SerieFollowersVM。這是與我們在App類中看到的導航的唯一的區別:其余的都是一樣的,這意味著我們調用NavigationServicetheNavigateAsync()方法,傳遞標識詳細信息頁面(DetailPage)和參數的關鍵參數。

重要事項!App類中,我們能夠自動使用NavigationService ,因為它繼承自PrismApplication 類。如果我們要在ViewModel中使用NavigationService (像在這種情況下),我們需要使用基于依賴注入(dependency injection)的傳統方法。NavigationService 實例已經在Prism容器注冊,所以我們只需要添加一個INavigationService 參數到MainPageViewModel的公共構造函數:

public MainPageViewModel(TsApiService apiService, INavigationService navigationService)
{
    _apiService = apiService;
    _navigationService = navigationService;
}

既然我們已經完成了導航到詳細頁面,我們就需要檢索DetailPageViewModel 類的參數。第一步,像我們為MainPageViewModel做的那樣,讓它從INavigationAware 接口繼承,除了BindableBase 類。通過這種方式,我們可以訪問OnNavigatedTo()事件:

public class DetailPageViewModel : BindableBase, INavigationAware
{
    private SerieFollowersVM _selectedShow;
    public SerieFollowersVM SelectedShow
    {
        get { return _selectedShow; }
        set { SetProperty(ref _selectedShow, value); }
    }
    public DetailPageViewModel()
    {
    }
    public void OnNavigatedFrom(NavigationParameters parameters)
    {
    }
    public void OnNavigatedTo(NavigationParameters parameters)
    {
        SelectedShow = parameters["show"] as SerieFollowersVM;
    }
}

前面的代碼顯示了如何處理我們從主頁收到的參數:同一個我們通過的MainPageViewModel對象到作為 OnNavigatedTo()方法的參數傳遞的NavigateAsync()方法。因此,我們可以用show 鍵簡單的檢索先前存儲的項。在這種情況下,因為我們預計SerieFollowersVM類型的對象,我們可以執行一個計算并將其存儲到稱為SelectedShow的ViewModel的屬性中。多虧了這個屬性,我們可以利用綁定到選擇顯示的各種信息連接到XAML頁面的空間。以下是DetailPage.xaml的樣子:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="//xamarin.com/schemas/2014/forms"
             xmlns:x="//schemas.microsoft.com/winfx/2009/xaml"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True"
             Title="{Binding Path=SelectedShow.Name}"
             x:Class="InfoSeries.Views.DetailPage">
  <StackLayout>
    <Image x:Name="InfoPoster"
           Source="{Binding Path=SelectedShow.Images.Fanart}" Aspect="AspectFill" />
    <Label Text="{Binding Path=SelectedShow.Overview}" LineBreakMode="WordWrap" FontSize="13" TextColor="#98a6ad" Margin="15" />
  </StackLayout>
</ContentPage>

內容很簡單:我們顯示show的圖片(存儲在SelectedShow.Images.Fanart屬性)和一段簡要描述(存儲在SelectedShow.Overview屬性)。

結束語

在這篇文章中,我們已經看到在用Prism 作為MVVM框架創建的Xamarin Forms應用程序中處理導航和依賴注入的一些基本概念。在下一篇文章中,我們將看到幾個高級場景,有關導航和特定于平臺的代碼的處理。你能在GitHub存儲庫找到這篇文章使用的示例應用程序(為了方便各位讀者,小編已經為大家整理了,請點擊這里下載)。

本文翻譯自:

 

PS: 關于移動開發,這些產品你可以關注>>
關于移動開發的最新資訊和產品推薦,請<>!

標簽:移動開發導航控件Xamarin

本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn


為你推薦

  • 推薦視頻
  • 推薦活動
  • 推薦產品
  • 推薦文章
  • 慧都慧問
掃碼咨詢


添加微信 立即咨詢

電話咨詢

客服熱線
023-68661681

TOP
美女下部隐私无视频 | 国产ppp视频 | 精精国产xxxx视 | 又黄又免费的视 | 最近日本中文字幕免费完整 | 欧美另类69 | 东方影院 | 亚洲精品一区二区三区视频在线观 | 韩国日本一区二区 | 国产全黄三级播放 | 美女国产毛 | 国产女与黑| 这里只有精品在线观看视频 | 白丝视频 | 亚洲精品国产高清 | 日本三级a∨在线观看 | 免费观看性欧美大片无片 | 一线路二 | 欧美视频一区 | 99精品国产 | 亚洲视频精品在线观看 | 国产亚洲视频网站 | 精品国产午夜福利不卡在 | 日韩午夜在线视频 | 无人在线观看视频高清播放 | 亚洲精品高清在线观看 | 国产午夜男女爽爽爽爽爽视频 | 中文字幕欧美在线观看 | 愉拍自拍一区首页 | 亚洲精品国产第一区二区尤物 | 欧美、另类亚洲日本一区二区 | 真实国产普通话对白乱子子伦视频 | 亚洲综合精品一区二区三区 | 国产亚洲精品一级在线观看 | 国产丝袜护土调 | 国产免费大片 | 中文字幕乱伦视频 | 欧美一区日韩二区在线观看 | 免费人成在线视频无 | 日韩欧美一区二区三区精品 | 亚洲国产欧美日韩v一区二区 | 91精品啪在线观看国产在线 | 91热爆在线精品 | 亚洲精品一本四区91 | 国产精品精品国产 | 青青草自产拍国产精品 | 欧美日韩在线一区 | 国产在线精品一区二区在线看 | 亚洲欧美日韩中文字幕在线不卡 | 亚洲专区日韩专区在线观看 | 成人精品久 | 成人三级在线播放 | 大地影视mv高清视频在线观看 | 国产一区二区三区水蜜桃 | 日韩精品午夜视频一区二区三区 | 日韩精品免费一区二区三区高清 | 性欧美vr高清极品 | 永久在线观看免费视频 | 五月天婷五月天 | 国产日韩欧美日韩欧美 | 特色特色的欧美大片 | 999国内精品永久免费观看 | 日韩欧美综合一区二区三区 | 又湿又紧又大又爽又a视频 日韩视频免播放在线观看 欧美亚洲日韩国 | 日韩综合在线欧美中文字幕 | 国产羞羞羞视频在线观看 | 国产乱码精品 | 日本黄页网址在线看免费不卡 | 99爱在线精品视频免费观看9 | 精产国品| 成都在线观看免费观看 | 亚洲精品天堂成人 | 国内老司机精品视频在线播出 | 免费在线观看的网站 | 首播电影网 | 国产又黄又爽又猛的免费视频播放 | 字幕a∨| 偷拍一区 | 国产精品亚洲а∨天堂2025 | 日本免费一区二区在线观看 | 日本最新免费二区 | 日本xxxxx在线观看 | 日韩一区二区在线 | 九九在线视频观看只有精品 | 风流老熟女一区二区三区 | 欧美日韩国产一线天午夜秀场 | 在线日韩日本国 | 91精品国产白丝jk在线拍 | 国产日产亚洲欧美综合另类 | 成都在线观看免费观看 | 丁香伊人 | 欧美激情办公室aⅴ | 小罗莉极品一线天在线 | 亚洲欧美中文日韩v在线 | 九九九热在线精品免费全部 | 亚洲欧美中文字幕国产 | 好吊日在线视频观看97 | 国产乱子伦农村叉叉叉 | 精品午夜国产福 | 欧美变态口味重另类在线视频 | 国产精成人品 | 美女人成大片免费视频看看 | 欧美日韩国产一中文字不卡 | 日本高清一区二区在线 | 亚洲成l人在线观看线路 | 伊伊人成亚洲 | 国内精品在线一区二区 | 日本欧美 | 日韩欧美一本书道一区二区 | 国产伦一区二区三区蜜桃 | 天天射天天添 | 国产福利日本一区二区三区 | 亚洲欧美日韩综合在线 | 成人欧美一区二区三区白人 | 日韩在线一区二区三区观 | 凌晨三点在线观看 | 亚韩精品视频二三四区 | 在线精品一区二区三区 | 日本一点不卡高清 | 巨爆中文字幕巨爆区 | 合集直播在线观看 | 中文天堂最新版资源 | 午夜男女羞羞爽爽爽视 | baoyu网址国产最新 | 日本三级香港三级人妇99 | 亚洲综合精品一区二区三区 | 亚洲自拍中文另类 | 欧美精品小视频 | 亚洲性色精品一区二区在线 | 黑人巨大videos极度另类 | 欧美性色生活免费观看 | 一区二区三区四区在线播放视频 | 肉色超薄丝袜脚交一区二区 | 国产r级福利在线观看 | 国产免费高清视频在线观看不卡 | 欧美日本国 | 日韩国产欧美在线观 | 国产又粗又爽视频 | 97青草最新免费精品视频 | 精品一二三四区 | 国产又粗又猛又黄又爽视频 | 国产欧美日本亚洲精品一5区 | 91全网在线观看国产 | 国产一区二区免费在线观看 | 91社区国产在线播放 | 这里只有精品在线视频 | 把伸进女人的www下载 | 不卡一卡 | 99视频精品全部国产盗摄视频 | 中韩欧美视频一区 | 国产免费不卡一区在线视频 | 亚洲欧洲电影一 | 五月婷婷丁香色 | 国产又爽又黄 | 视频在线看免费观看 | 黑人精品一区二区三区不卡 | 风流老熟女一区二区三区l 国产亚洲精品国产福利 | 免费国产自在线拍 | 午夜老司机永久免费看片 | 999电影网| 亚洲人成伊人 | 区三区在线观看 | 亚洲欧美综合区自拍另类 | 亚洲五月花在线观看 | 精品大臿蕉视频在线观看 | 天天射天天爱天天射干 | 国产国语 | 激情在线观看视频 | 中文字幕人成 | 老师喂我乳我脱她内裤 | 国产免费a视频网站在线观看 | 国产自在线观看免费视频 | 国产在线精品成人一区二区 | 自拍偷自拍亚洲精品偷一 | 八戒成年私人影院 | 成人性生交大片在线观看 | 欧美视频亚洲视频日韩动漫 | 精品免费美剧网排行榜在线看 | 国产精品免费大片 | 免费电影资源 | 国产精品v欧美 | 国产亚洲人成网站观看 | 欧美日韩在线播放一区二区三区 | 免费版在线观看 | 欧美一级高清视频在线播放 | 国产福利不卡视频在免费 | 99热精 | 日韩在线精品一区二区三区 | 色色一区二区 | 国产精品午夜自在在线精品 | 水蜜桃成视频人在线看 | 国产乱码精 | 不要播放器看在线播放a国产 | 亚洲无线码高清在线观看 | 亚洲欧美成ⅴ人在线观看 | 中文字幕午夜福利片亚洲 | 亚洲国产日韩一级精品视频网站 | 日韩新片王网 | 亚洲欧美另类专区 | 日韩在线视频线视频免费 | 国产精品成人va在线观看 | 动漫美女无| 国产一在线精品一区在线观看 | 精品国产手机自 | 丁香婷婷六月综合缴清 | 热播电视剧大全 | 日韩中文字幕网先锋资 | 欧美日韩另 | 欧美精品v日韩精品v韩国精品v | 免费高清乱伦无 | 理论片在线观看 | 国产精品日韩欧美一区二区三 | 囯产精品宾馆在线精品酒店 | 免费一级欧美片在线观看 | 日韩精品一区在线观看 | 免费人成年激情视频在线观看 | 欧美日韩亚洲国产精品 | 特黄a三级三级三级视频 | 五月桃花网婷婷亚洲综合 | 天堂网果冻传媒 | аⅴ资源中文在线天堂 | 国产一区二区三区在线播放 | 免费人成视频年轻人在线无毒不卡 | 精品国产品国语 | 亚洲国产高清视 | 欧美色吊丝人人添人人摸 | 免费精彩视频 | 国产影视 | 欧美日韩亚州在线 | 精品h一区不卡免费视频国产 | 中文字幕在线免费观看 | 国产精品视频第 | 免费人成在线观看vr网站 | 国产色系视频在线观看免费 | 国内精品视频在线中文字幕 | 二区62 | 日本在线观看一区 | www国产亚洲精品 | 精品国产福利第一区二区三区 | 欧美日韩深夜视频在线观看 | 老女肥女熟国产在线视频网址 | 国产电影在线观看 | 成人免费观看视频 | 色色一区二区 | 亚洲人精品亚洲人成在线 | 老鸭窝laoyaw | 国产小呦泬泬99精品 | 中文字幕日本有码视频在线 | 亚洲视频一区二区 | 亚洲国产精品第一区二区 | 最近免费中文字幕大全免费版视频 | 成版人抖音d2视 | 日韩在线视频 | 奇米影视77 | 亚洲欧美一区二区三区在线 | 国内成人精品亚洲 | 精品午夜国产在 | 91精品国产午夜在线免费观看 | 国产精品福利资源在线 | 日韩专区第一页 | 亚洲精国产一区二区三区 | 日韩欧美一区二区三区视频在线 | 日日摸夜夜 | 亚洲处破女 | 国产美女视频福利 | 免vip免费观看热播电 | 欧美区一区 | 国产人在线成免费视频 | 国产亚洲制服 | 国产探花 | 欧美国产激情一区二区三区蜜月 | 日韩男女激情视频在线观看 | 国产精品丝袜亚洲熟女 | 99精品视频在线视频免费观看 | 亚洲午夜视频在线观看 | 国产欧美一区二区三区综合野 | 激情国产原创在线观看 | 大地资源在线观看免费中文版 | 热99r| 91制片厂职场冰与火 | 青柠影院免费观看电视剧高清 | 日韩高清在线高清免费 | 一区二区日韩激情综合网 | 精品国产一区二区三区a | 日本免费一区二区五区六区 | 日本不卡 | 国产精品欧美一区 | 亚洲熟女 | a级国产乱理伦片在线观看 天美传媒官方网站 | 国产精品自产拍在线观看55 | 不卡精品| 产免费一区二区三区视频 | 日本三级免费 | 日韩精品一线二线三线优势 | 羞羞影院午夜男女爽爽 | 午夜视频在线播放 | 亚洲中文字幕精品一区二区三区 | 日韩欧美天堂 | 凄辱护士日本电影免费看 | 免费高清直 | 三级a在线视频观看永久 | 国产亚洲美女精品 | 女の乳搾りです在线观看 | 青青青国产在线观看 | www.五月天激情 | 成人午夜视频 | 欧美视频在线视频精品 | 亚洲精品中文字幕乱码三区 | 中文字幕久 | 色两性午夜视频免费观看 | 国产亚洲无 | 欧美特级特黄aa | 九九热免费在线观看 | 精品日韩一区 | 亚洲精品二区国产综合野狼 | 天天综合7799精品影视 | 中文日产 | 最近中文字幕高清mv免费 | 国产又粗又黄又爽的免费视频 | 欧美性猛交xxxx黑人 | 最新理论片在线观看免费 | 国产精品亚洲五月天高清 | 神马家庭影院 | 色国产综合免 | 欧美多人顶级午夜寂寞影院 | 无线资源国产资源好片欧美 | 精品国产二区亚洲日本精品 | 亚洲精品国精 | 欧美日本道 | 欧美激情片区一区二区三区 | 区中文字幕 | 愉拍自拍另类高清 | 欧美日韩人人天天综合小说 | a级日韩乱理伦片 | 国产亚洲欧美日韩国产片 | 国产在线国偷精品产拍 | 欧美在线观看精品国产 | 欧美日韩另类视频在线观看 | 国产精品日韩精品在线播放 | 亚洲欧美日韩国产精品专区网 | 2025最新国产在线看 | 一级毛卡 | 欧美在线激情视频 | 丁香九月月小说图片区 | 午夜福利精品 | 日本有码中文 | 国产免费a视频网站在线观看 | 亚洲国产精品资源 | 自拍偷亚洲成在线观看 | 亚洲无限 | 亚洲一区在线视频在线观看 | 亚洲国产日韩不卡线欧美 | 亚洲日本欧美日韩高观看 | 2025最新在线观影网站 | 国产性生大片免费观看性 | 亚洲国产精品福利片在线观看 | 国产桃色在线成免费视频 | 国产日产亚洲欧美综合另类 | 夜夜未满十八勿进的爽爽影院 | 人人添逼人人摸人人 | 亚洲欧美国产日产综合不卡 | 99热这里只有精品23 | 欧美精品自拍一区 | 丝袜一区二区高跟鞋 | 亚洲精品高清欧美 | 日本三级中文字版电影 | 日本欧美真人三级在线a | 人成在线免费视频 | 亚洲成a人片在线v观看 | 最近中文字幕2025免费 | 日本免费在线观看视频 | 精品中文| 国产亚洲男人的天堂在线观看 | 欧美日韩国产 | 亚欧免费大片在线观看 | 91国内揄拍国内精品对白 | 日本一区二区在线观看精品 | 老司机亚洲精品影院 | 国产亚洲h网 | 国产手机在线 | 亚洲精品国产v片 | 国产免费一级视频在线观看 | 国产原创91| 欧洲美熟女乱又伦 | 国产视频a区 | 国产亚洲日韩网爆欧美 | 国产精品v片在线观看不卡 国产亚洲精品午夜福利 | 日韩精品一区在线观看 | 亚洲成a人v欧美综合天堂 | 国产日韩免费视频在线观看 | 挤奶在线| 拍拍拍无挡国产精品 | 三年片在线观看免费大全电影 | 手机看片福利 | 天美传媒、91制片厂、天美传媒 | 国产国产人免费视频成69大陆 | 小说区图片区激情区视频区 | 欧美午夜理伦三级在 | 国产又色又爽又黄又刺激的视 | 国产女女互摸互慰在线观 | 亚洲精品色午夜 | 国产不卡高清在线观看视频 | 男女肉车 | 国产伦精品一区二区三区在 | 在线观看片免费人成视 | 97香蕉国产免视频网站 | 国产免费私拍一区二区三区 | 国产亚洲美女嘘嘘国产 | 国产欧美亚 | 国产亚洲精品一级在线观看 | 国产又黄又猛又粗又爽的a 羞羞影视 | 国产精品免费视频网站 | 国产免费一区二区 | 欧美综合亚洲 | 亚洲国产精品国语在线 | 国产舌乚八伦偷品w中 | 亚洲性日韩精品一区二区 | 亚洲天堂网一区二区三区四区 | 成色伊人| 国产高清狼人香蕉 | 国产freexxxx| 中文字幕国产在线观看 | 午夜福利国产主播露出 | 一级视频在线播放 | 日韩欧美在线 | xxxx自由视频 | 欧美乱伦国产精品 | 欧美激情亚洲一区中文字幕 | a级精品九九九大片免费看 婷婷亚洲久悠 | 日本免费一区二区三区在线看 | 乱理伦片在线播放 | 欧美日韩一区二区综合 | 亚洲日韩一区二区一 | 日韩中文免费视频 | 欧美高清一区二区三区不卡视频 | 娇小teen乱子| 亚洲不卡| 国产女人喷潮视频在线观看 | 欧美精品在线一区二区三区 | a级全黄试看30分钟gif动图 | 成人免费大片黄在线播放 | 国产在线观看第二十三页 | 亚洲国产专区一区 | 午夜福免费福利在线观看 | 日本影片一区二区 | 天天看片在线完 | 国人精品视频在线观看 | 国产精品人 | 日韩精品中文字幕视频在 | 妖精视频| 国产精品一区欧美日韩制服 | 激情综合在线亚洲五月天 | 又爽又大又光又色的午夜视频 | 2025最新国产在线精品不卡顿 | 黄瓜视频在线播放看片 | 亚洲日本成本人观看 | 国产手机精品一区二区 | 欧美日韩一区二区成人午夜电影网 | 暖暖日韩欧美视频免费 | 亚洲国产中文国产一区二区三区 | 车上乱肉合 | 国产精品视频一区 | 亚洲无线码一区国产欧美国日产 | 国产小视频福利在线观看高清完整 | 十九岁中国电影在线观看免费 | 521国产精品网站在线观看 | 日韩亚洲 | 亚洲精品综合 | 日本高清视频www | 日本精品视频在线 | 一区二区中文字幕 | 国内精品久 | 欧美精品亚洲精品日韩专区 | 国产丁香婷婷在线亚洲视频 | 欧美日韩国产yw在线 | 日韩一区二区三区四区区区 | 观看一区二区视频 | 亚洲午夜成人精品电影在线观看 | 欧美黑大硬粗xxxxx成人视颎 | 国产伦码精品一 | 91制片厂一样的应用 | 欧美日韩在线一区二区三区 | 国产欧美日韩精品在线观看 | 91桃色在线看片 | 亚洲一区二区三区人人 | 性猛交╳xxx乱大交 欧美午夜理伦三级在线 | 亚洲人成电影院在线观看 | 欧美嫩交一区二区三区 | 欧美性色生活免费观看 | 国产精品一区二区制服 | 国产a国产国产片 | 日韩精品欧美一区喷 | 91精品一区国产高清在线 | 日韩国产 | 亚洲色偷偷偷鲁综合 | 中文字幕一区二区精品区 | 欧美精品人在线观看 | 日本特大a级猛片在线观看 国精产品999国精产 | 国产美女一级a视频欧洲 | 国产日本卡二 | 亚洲中文字幕在线一区播放 | 免费国产网站在线观看不卡 | 欧美国产精品 | 亚洲欧美一区二区三区国产 | 亚洲第一页乱 | 日韩精品欧美精品国产精品 | 欧洲尺码日本尺码专线 | 人成精品视频三区二区一区 | 野花高清在线 | 国产高清日本综合 | 亚洲国产欧美在线一区二区 | 国产亚洲精品影视在线产品 | 欧美亚洲一区二区三区 | 一区二区三区四 | 在线日韩中文字幕 | 亚洲一区二区三区高清视频 | 亚洲女人天堂网 | 亚洲欧美韩国三级 | 国产精品视频免费一区二区 | 国产精品乱码高清在线观看 | 午夜一区一品日本 | 国内永久福利在线视频 | 午夜国产在线一区二区三区 | 国产老熟女老女人老人 | 国产精品资源站在线 | 国产高清在线精品一本大道 | 日本国产性爱观看视频 | 9999热| 在线观看男人的 | 精品成人一区二区三区电影 | 亚洲男人的天堂在线观看 | 91区国产福利在线观看午夜 | 2025年最新热播电影 | 国产精品一区二区亚瑟不卡 | 看国产黄| 成人激情视 | 亚洲国语中文字幕理论片 | 精品免费在线 | 爱情岛亚洲论坛 | 99久国产精品午夜性色福利 | 日韩一区二区三区四区区区 | 日本国产欧美精品在 | 最新国产精品拍自在线播放 | 最新好看的电视剧免费在线观看 | 成人污污国产在线观看 | a国产片免费看视频 | 91啪在线观看国产在线 | 国产精品自在线拍国产 | 永久免费精品影视网站 | 日韩一本之道一区中文字幕 | 亚洲国产高清 | 国产精品亚洲综合天堂夜夜 | 免费人成动漫在线播放r1 | 91精品国产白丝jk在线拍 | 国产精品186在线观看在线播放 | 亚洲色精品一区二区三区 | 日本免费看黄 | 国产国产人成免费视频77777 | 99玖玖爱在线精品免费观看 | 精品国产蜜桃臀在线观看 | 大伊香蕉在线精品视频75 | 国产精品尤物在线 | 国产91最新欧美在线 | 日本精品大乳一区 | 无人在线视频高清免费观看 | 三级高清精品国产 | 好硬好大| 亚洲国产精品综合一区在线 | 亚洲变态欧美另类精品 | 国产精品区二区三区日本 | 国产精品第一页第一页 | 91高清免费国产自产拍不卡 | 久热国产vs视频在线观看 | 免费人成年短视频免费网站 | 国产午夜理论不卡在线观看 | 国产激情怍爱视频在线观看 | 国产精品综合色区在线 | 国产亚洲欧美日韩高清专区 | 中文字幕v | 东方影院| 精品免费国产一区二区三区四区五 | 亚洲成aⅴ人片久青草影院 国产91精品系列在线观看 | 最近免费中文字幕大全 | 国产视频精 | 亚洲熟女激情秒播 | 91大神在线视频免费观看 | 免费成人激情在线 | 女教师巨大乳孔中文字幕 | 中文字字幕乱码高清二本道资源站 | 天美麻花星空免费观看乡村版 | 年轻的母亲4韩剧免费中文版 | 一区二区日韩视频九一蜜桃 | 91精品手机国产在线观 | 人人鲁人人莫人人爱精品 | 国产户外一 | 97在线观看免费视频观看 | 女人18毛多水多 | 花蝴蝶免 | 国产亚洲 | 亚洲欧美日本国产—区二区三区 | 偷自拍亚洲视频 | 国产午夜三级一区二区三 | 国产91剧情在线观看 | 黑人巨大精品欧美一区在线 | 热99re6久精品国产首页青柠 | 国产日产一区二 | 精美日产| 国产99视频精品免费视频6 | 日韩精品电影一区亚洲 | 日本一本之道之视频在线不卡 | 国产在线观看色窝网 | 国产精品香蕉在线的人尹人 | 国产精品国产高清 | 日本在线视频在线 | 欧美伦理一区 | 国产精品美 | 勃起又长又黑又粗毛又多 | 国产精品亚洲无线码在线播放 | 国产乱码在线精品可播放 | 国产亚洲精品九九久在线观看 | 欧美激情va永久在线播放 | 国产玩弄醉 | 亚洲欧美一区二区三区国产 | 九一香蕉| 国语自产精品视频一区二区 | 国产午夜男女爽爽爽爽爽视频 | 日韩成人精品在线 | 国产午夜伦伦午夜伦 | 免费a视频在线观看 | 韩国床戏激情戏裸戏 | 最新欧美精品一区二区三 | 国产免费私拍一区二区三区 | 国产在线精品国偷产拍 | 办公室激情上司和秘书小说 | 亚洲日本va在线视频观看 | 国产精品免费视频观看拍拍 | 女の乳搾りです在线观看 | 国产91免费视频 | 电影网在线好看 | 一区二区亚洲精品国产片 | 性xxxx视频播放 | 亚洲卡一卡二卡三乱草莓 | 性欧美大战 | 奇奇影院 | 日韩精品免费一区二区三区高清 | 亚洲精品在看在线观看 | 精品区一| 国产精品第1页 | 欧美精品亚洲精品日韩专区v | 亚洲国产日韩一级精品视频网站 | 国产综合在线91精品思思 | 国产美女高清片免费观看 | 野外性史 | 韩国主播 | 国产亚洲播放在线 | 国产jjizz女| 国产午夜福利在线观看污 | 亚洲无砖砖区免费 | 亚洲无线 | 欧美日韩免费一区二区在线观看 | 成人午夜又粗又硬又长 | 日本乱理伦片在线观看中文 | 亚洲一区在线播放 | 2025亚洲精品极品色在线 | 男插女下| 成人免费动作大片黄在线 | 迷奷系列在线播放456 | 精品国产第一页 | 国产精品美女一区二区三区 | 日本特黄特色aaa大片免费 | 91精品免费国产高清在线 | 国产伦精品一区二区三区精品 | 亚洲一区二区三区香蕉 | 国产老色批视频在线观看应用 | 亚洲人成电影手机在线网站 | 天美传媒 | 98视频在线| 最新好看的电视剧免费在线观看 | 国产精品办公室沙发 | 又大又粗又硬又黄的免费视频 | 在线观看日韩欧美一区二区 | aⅴ在线视频男人的天堂 | 国产激情视频网站 | j8又粗又大又长又爽又硬电影 | 美女视频黄频a美女大全 | 豆奶视频官网下载 | 48国产吹潮在线观看 | 天堂在线8一区二区三区 | 国产l精品国产亚洲区在线观看 | 国产精品另 | 日本精品不卡在线观看 | 亚洲aⅴ男人的 | 亚洲日韩一区精品射精 | 国产青草视频在线观看 | 国产精品臀控福利在线观看 | 国产亚洲精品午夜高清影院 | 国产婷婷综合在线精品尤物 | 96精品专区国产在线观看高清 | 日韩一区二区手机免费观看 | 免费人成视频年轻人在线无毒不卡 | 区二区三区综合片 | 欧美日韩中文字幕免费看 | 国产馆精品推荐在线观看 | 精品亚洲视频在线观看 | 免费的电影天堂手机在线观看 | 黑人巨大精品欧美视频一区 | 夜鲁鲁鲁夜夜综合视频 | 国产福利在线观看视频 | 女人天堂在线观看国产 | 97人人揉人人捏人人添电影 | 国产又粗又大又黄的视频 | 三年片最新电影免费观看 | 国产亚洲无 | 国产在线精品手机播放 | 蜜桃影视 | 欧美色欧洲免费无线码 | 大色综合色综合网站 | 国产对白普通话视 | 日韩亚洲制服另类 | 国产精品翘臀在线播放 | 亚洲国产中文字幕 | 香港三级日本三级韩国三级 | 探花视频在线 | 国产二区三区午夜免费视频 | 国产深夜在线免费观看 | 手机看片1024欧美日 | 成人午夜电影网十八岁勿入 | 日韩在线观看视频网站 | 伦理大片在线观看 | 欧美综合区自拍亚洲综合 | 免费高清欧美一区二区三区 | 中文字幕卡通动漫精品首页 | 热映电影免费在线观 | 91桃色在线免费观看 | 国产伦一区二区三区蜜桃 | 精品在线看 | 91美剧网 | 亚洲欧洲日产国码久在线观看 | 天天被干免费观看视频 | 另类欧美日韩精品一区二区在线 | 免费人成视频在线播放视频 | 国产精品va在线观 | 亚洲色精品三区二区一区 | 亚洲日本欧美日韩高观看 | 日韩成人免费 | 香港三级日本三级韩国三级 | 国产乱子伦午夜视频观看 | 亚洲欧美日韩中文在线制服 | 手机免费看一级 | 在线欧美日韩精品一区二区 | 欧美精品亚洲精品日韩传电影 | 最新中文字幕在线观看免费不卡 | 精品国产一区二区三区免费91 | 国产综合在线观看 | 中字幕一区二区三区乱 | 三区免费高清视 | 97一区二区在线播放 | 国产精品素人福利 | 国产情侣套 | 字幕一区二区三区四区 | 国产精品一区二区国产馆蜜桃 | 精品国内自 | 国产精品第三页 | 国产成年人精品一区二区 | 亚洲中文字幕一区精品自拍 | 九色91| 欧美激情中文字幕一区二区 | 成人啪精品视频免费网 | 国内精品一区二区 | 欧美日韩在线播放一区二区三区 | 飘花在线影院 | 国产夜色精品视频伊甸园 | 国产日韩综合精品一区二区三区 | 欧美巨大德国肥婆 | 日韩欧美三级理论在线观看 | 亚洲国产精品免费在线观看 | 日韩午夜伦| 国产自经典三级在线观看 | 亚洲加勒| 久9视频这里只有精品8 | 国产福利萌白酱精品tv一区 | 国产又粗又猛 | 三年片大全在线观看免费观看大全 | 欧美一级在线全免费 | 日本夫妻激情生活b区 | 成人福利在线视频免费观看 | 亚洲欧美在线精品一区二区 | 日韩亚洲欧美中文高清 | 日本黄页网 | 精品国产亚洲一区二区三区在线观 | 亚洲日韩福利在线 | 99国产精品9 | 中文天堂www | 快活影院永久地址 | 国产亚洲无 | 精品一区二区三区视频免费 | 亚洲中文字幕一二三四区 | 亚洲日本一线产区和二线产 | 久青草国产在视频青草99在 |