国产凹凸在线-国产拗女一区二区三区-国产白白视-国产白领-国产白拍-国产白丝jk被疯狂输-国产白丝喷-国产白丝在线

金喜正规买球

logo 移動開發學習指南
文檔金喜正規買球>>移動開發學習指南>>Xamarin Forms的Prism第二部分:基本導航和依賴注入(Dependency Injection)模式

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


前一篇文章中,我們已經開始介紹在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已經連接?,F在我們需要通過ListView控件中所選條目到新頁面。讓我們先看看如何在主頁處理選擇。通過使用由我親愛的朋友Corrado Cavalli創建的庫,我們會得到一些幫助,它允許你在Xamarin Forms應用程序實現行為??捎玫男袨橹械?strong>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: 關于移動開發,這些產品你可以關注>>
關于移動開發的最新資訊和產品推薦,請<>!
掃碼咨詢


添加微信 立即咨詢

電話咨詢

客服熱線
023-68661681

TOP
a亚洲欧美日韩在线观看 | 日本精品专区在线 | 国产精品电影在线 | 99在线精品国产不卡在线观看 | 91精品国产免费青青碰 | 这里只有精品在线视频 | 成人三级视频在线观看不卡 | 韩国十九 | 国产精品天干天干在线综合 | 美女遭强| 免费成人午夜激 | 亚洲国产丝袜一区二区 | 亚洲午夜视频在线观看 | 欧美亚洲一区二区三区导航 | 国产a级三级三级三级 | 国产卡一卡二卡四卡无卡 | 日韩欧美手机在线视频 | 中国免费xxxx视频在线观看 | 欧美亚洲国产精品第 | 精品日韩国产一区 | 国产欧美日韩综合精品一区二区三 | 日韩区欧美国产区在线 | 久热这里只有精品99在线观看 | 思思精品| 亚洲一区二区三区国产精华液 | 欧产日产国产精品精品 | 99re6在线视频精品免费下载 | 国产污污污十八在线精品观看 | 国产午夜成福利在线观看 | 国产超清精品在线观看 | 欧美一区二区三区精品国产 | 色偷偷人人澡人人添老妇人 | 日本一区二区三区不卡视频中 | 不卡中文字幕激情视频网站 | 韩国成人精品久 | 中文字幕电影一区二区 | www.成人影片| 亚洲性人人天天夜夜摸 | 欧美精品天堂一区二区不卡 | 中文字幕人成人乱码亚洲电影 | 免费电影推荐 | 亚洲一区在线精品 | 国产亚洲精品日本亚洲网站 | 一级一片免费播放 | 亚洲国产97视频在线 | 欧美黑人又粗又大又爽免费 | 亚洲国产2025精品无 | 日本激情夜里视频在线观看 | 国产精品最新免费视频 | 国产精品美脚玉足在线 | 三级中文字幕永久在线视频 | 国产亚洲精aa在线观看see | 欧美日韩一区二区三区高清在线 | 日韩丝袜| 欧美xx在线 | 国产精品人娇在线内谢 | 亚洲日本欧美日韩髙清观看 | 成在线人视频免费视频 | 亚洲骚熟女性视频 | 美女福利亚洲视频 | 亚洲日韩欧美一区二区三区在线 | 日韩欧美综| 91看片婬黄大片91挑色 | 国产一二三四区乱码免费 | 欧美日本一区二区视频在线播放 | 影视大全电视剧在线播放 | 亚洲视频中文字幕在线 | 精品国产电影在线 | 国产小视频在线观看 | 午夜男女福利 | 一区二区三区四区在线观看视频 | 能看的国产乱片在线 | 日韩午夜免费电影 | 日韩精品综合丝袜制服 | 欧美v国产v亚洲v日韩九九 | 日韩精品一线二线三线优势 | 国产乱老熟视频 | 曰本还a大片免费视频 | 精品国精品国产自在久国产87 | 国产永久免费高清在线 | 成人国产福利在线观看 | 国产亚洲欧美精品一区二ti | 又大又硬又爽免费视频 | 欧美日产国产首 | 精品国产精品国产自在久国产 | 欧美激情国产日韩精品一区18 | 日韩精品另类天天更新影院 | 亚洲精品久荜中文字幕 | 色老板在线精品免费视频 | 欧美三级在线观看国产 | 国产亚洲精品mv第十页 | 欧美一级日韩一级亚洲一级va | 大地影院mv在线观看视频免费 | 日韩视频怡春院 | 国产喷潮在线播放一 | 欧美高清一区二 | 69精华国产精华精华液 | 中文字字幕在线精品乱码高清 | 国产99对白在线播放 | 加勒比精品 | 另类图片 | 日本有码中文字幕第一页在线播 | 涩涩视频午夜福利一区二区 | 亚洲精品国偷自产在线 | 成欢阁免费入口在线观看 | 精品视频日韩一区二区三区 | 国产大片91精品免费看3 | 欧美日韩一区精品在线 | 免费看一级特黄a大片 | 欧美精品一区免 | 国产色a在线观看 | 国产又黄又粗又色又刺激视频 | 欧美三级极品视频在线观看 | 91福利社区在线试看一分钟 | 日本欧美 | 国产va免费高清在线观看 | 国产精品日韩专区一区二区 | 亚洲精品一区二区国产精华液 | 欧美性理论片在线观看片免费 | 91欧美精品综合在线观看 | 免费激情视频网站 | 亚洲va综合va国产产va中文 | 精品九九 | 一区二区亚洲综合制服欧美 | 欧美日韩一区二区三区高清在线 | 日韩本免费一 | 国产私人视频在线播放 | 日韩成人国产精品视 | 99国产这里有精品 | 重口sm一区二区三 | 欧美亚洲日韩 | 730099带你另眼看世界 | 91精品啪在线 | 国产大奶子在线播放免费 | 国产视频91尤物在线观看 | 国产欧美日韩精品a在线观看高清 | 国产蜜片免费在线观看播放 | 在线看推理网站 | 日韩亚洲精品影视 | 国产一区二区熟女精品免费 | 国产吹潮视频在线观看 | 亚洲人成一区在线 | 欧美日本一区二区三区在线 | 99精品欧美| 成年人24小时在线免费观看视频 | 国产一区在线视 | 国产精品免费观看网址入口 | 国产精品福利尤物youwu | 精品国产人成在线 | 中文字幕亚洲欧美在线不卡 | 国产伦理一区二区 | 国产欧美日韩午夜在线观看 | 日韩一区二区三区美女 | 性色生活片在 | 日本有码中文字幕第一页在线播放 | 精品国产高清一区二区三区人 | 日韩欧美视频在线观看视频不 | 国产制服国产制服一区二区 | 国产福利短视频在线播放 | 夜色国产精品欧美在线观看 | 99精品无人区乱码在线观看 | 国产一区在线视 | 亚洲精品天天影视综合网 | 国产伦理精品 | 国产亚洲欧美日韩综合一 | 国产精品一级婬片免费 | 热播电视剧电影高清免费在线观看 | 国产亚洲91精品色在线 | 欧美日韩国产亚洲综合网一区 | 国产成本人片 | 日本中文字幕网 | 国产精精品免费观看 | 综合乱伦自拍三 | 女人18毛 | 亚洲aⅴ无| aa免费视频观看网站 | 青苹果乐园影院在线播放 | 91福利影院 | 尤物国产精品福利三区 | 观看免费视频 | 韩日精品一区二区 | 精精国产xxxx视频在线 | 中文字幕在线不卡 | 精品欧美一区二区三区四区 | 亚洲专区在线 | 欧美日韩最新一区二区三区 | 中文字幕乱码亚洲中文在线 | 亚洲加勒 | aa中文字幕在线观看 | 亚洲成综合人在线播放 | 午夜伦理电影网 | 国产日产高清欧美一区二区三区 | 国产在观线 | 日韩欧美一区二区3d视频 | 久热热热 | 免费人成视频年轻人在线无毒不卡 | 精品国产色欧洲激情 | 日韩精品视频网站在线 | 亚洲国产日韩欧美视频一区 | 天天夜碰日日 | 亚洲欧美va动漫一区二区 | 亚洲人成网 | 日本一区二区三区在线观看网站 | 最近中文字幕完整版2025一页 | 国产在线观看 | 精品国产精品 | 免费高清电影电 | 国产伦精品一一区二区三区高清版 | 国产精品推荐制服丝袜页 | 欧美a级片一区二区在线播放 | 成在线人免费视频 | 日韩一区免费视频99 | 国产女人aaa级久 | 日韩欧美亚洲一中文字暮 | 国产精品日韩综合图片 | 日本伊人精品一区二区三区 | 欧洲北美性爱逼逼视频图片 | 欧美刺激性大交 | 美丽的姑娘高清版在线观看 | 亚洲精品分类在看在 | 欧美日韩精品一区二 | 日本中文有 | 日本阿v视频高清在线中文 银杏影视 | 射射影院| 99re6久| 日本久本草 | 在线观看免费视频网站a站 国产1区 | 两个人高清在线观 | 亚洲v天堂v影 | www在线观看一区二区三区 | 日本激情 | 费精品国产一区国产精品剧情在线 | 潦草影院 | 国产精品一区二区亚瑟不卡 | 国产视频动漫 | 日韩午夜成人精品免费网 | 免费国产人成网站在线播放 | 女同另类国产精品视频 | 国产精品伊人 | 日韩欧美一区二区在线观看 | 特殊重囗 | 亚洲国产日韩a不卡线欧美 国产精品成人一区二区三区 | 日本www视频男人的天堂 | 日韩高清一区在线观看 | 夜夜橾天天橾 | 亚洲无线观看国产超清 | 国产91精品高清一区二区三区 | 99在线精品免费视频九九 | 91精品国产一区二区三区香蕉 | 国内精品视频一区电影 | 浓毛老太交欧美老妇 | 最新高清电影在线免费观看 | 亚洲综合国产一区二区三区 | 欧美亚洲一 | 欧美日韩国产无限码一区 | 国产一级高清在线 | 国产日韩精品一区二区三 | 国产香蕉一区二区在线网站 | 日本dvd专区中文在线 | 久99精 | 精品国产亚洲欧美在线 | 巜大学生特殊 | 日韩精品一区二区在线看 | 91精品国产亚洲爽啪在线观看 | 欧美1区2区3 | 国精产品999一区二区三区有 | 欧美三区日韩一 | 国产成在人线在线播放 | 青青草中文字幕在线观看 | 欧美日韩综合不卡一区二区三区 | 欧美顶级情欲片在线播放 | 亚洲精品亚洲人成在线播放 | 看日韩精品视频在线观看 | 青青青国产 | 国产网址 | 国产精品美女网站在线观看 | 亚洲国产2025精品无 | 国产综合精品一区 | 国产精品成人免费观看 | 欧美在线观看精品国产 | 日韩欧美亚洲国产ay | 福利一区二区三区视频在线观看 | 国产综合欧美无毒不卡怡红院 | 欧美性xxxxx极品老少 | 久青草影院在线观看国产 | 在线观看的精 | 成年人免费在线观看视频 | 日韩高清在线第一页 | 国产3区| 国产无吗 | 国产亚洲高清不卡在线 | 福利搞笑电影 | 菠萝菠萝蜜视频在线观看免 | 国产伦精品一区二区三区男技 | 国产又爽又黄 | 性欧美video高清 | 国产在线中文字幕a天堂 | 国产精品多p对白交换绿 | 免费人成视频在线播放视频 | 高清欧美日韩 | 国产精品综合亚洲 | 国产一区中文字幕 | 国产系列丝袜熟女精品网站 | 欧美在线国产精品 | 国产高清亚洲免费片 | 青青草中文字幕在线观看 | 日本高清视频一区 | 成人国产综合三级 | 欧美激情国产日韩在线 | 亚洲日韩国产欧 | 91视频免费看 | home视频在线观看日本 | 猛片亚洲成a∨人片在线观 精品国产福利在线观看 | 一本精品| 国产精彩乱子真实视频 | 国产亚洲国语精品自产拍在线 | 亚洲欧美日韩精品色xxx | 国产综合在线观看一区 | 91露脸对白不带套在线播放 | 国产高清视频在线免费观看 | 三级视频网站在线观看 | 亚洲一区二区三区丝袜 | 午夜免费福利在 | a区b区c区线路入口 国产网站一区二区三区导航 | 精品综合国产一区二区三区码码 | 国产精品丝袜在线观看首页 | 欧美一片毛国产在线视频 | 国产亚洲精品午夜福利巨大 | 欧亚一卡二卡3卡四卡精品 日本一区二区 | 国产视频精品分类 | 国产免费专区 | 亚洲v日韩v欧美高清在线观看 | 国产熟女一区二区三区五月婷 | 精品国产自在现线免费观看 | 日韩一区二区三区四区五区 | 综合一区 | 黄+片在线免费观看+精品+巨 | 欧洲亚洲国产日韩综合一区 | 欧美亚洲日韩aⅴ在线观看 在线综合亚洲欧美日韩手机版 | 国产精品夜间视频香蕉 | 日韩福利在线观看 | 国产福利一区二视频播放 | 精品国产不卡女 | 国产欧美一区二区精品性色tv | 精品国精品国产自在久国产不卡 | 日韩精品一区不卡 | 国产素人视频在线播放 | 一起草视频在 | 国产日韩综 | 日本免费特黄一区二区 | 国产ts人妖系列 | 欧美日韩在大午夜爽爽影院 | 亚洲精品视频在线播放 | 欧美国产一区二区三区 | 大片视频网站观看 | 在线欧美精品二区三区 | 精品日本亚洲影视 | 国产灌醉迷晕在线精品 | 日本护士喷水 | 成人性爱视频在线观看 | 国产3344视频在线观看 | 91制片厂一样的应用 | 国产精品亚洲欧美动漫卡通 | 免费观看日韩黄 | 欧美网站免费观看在线 | 日韩免费一区二区三区中文字幕 | 国产欧美一二三区男女交配 | 第一国产综合高清 | 国产美女主播在线观看 | 综合欧美一区二区三区 | 欧美国产日韩a在线视频 | 日韩精品欧美一区二区 | 精品第一区视频二区 | 为您提供国产成 | 日韩精品在 | 欧美亚洲国产日韩综合在线播放 | 中文字幕制服丝袜在线观看 | 国产精品线在线精品 | 视频h在线观看 | 欧美另类一区二区在线观看 | 欧美aⅴ菲菲影视城视频 | 国产亚洲成a | 欧美激情一区二区三区高清视 | 色人阁第四色 | 国产丰满老熟女重口对白 | 欧美日韩第一页中文字幕 | 91精品啪在线观看国产在线 | 日韩在线视频一区 | 国产片婬 | 日韩在线观看视频免费 | 无人在线观看高清视频 | 高清在线观看 | 欧美精品一区二区男同专区 | 国产免费一区二区三区视频 | 热播电视剧在线观 | 欧美日产国产首页 | 中文字幕亚洲无线码一区女同 | 区小说区激情区 | 国产精品宾馆在线精品酒店 | 国产一区二区在线视频 | 国产日韩综合一区在线观看 | 成人免费视频一区二区 | 成年人视频www | 爱丫爱丫影院官网 | 国产精品视频网站丝袜 | 国产精品网站在线观看 | 一本大道 | 超刺激高跟鞋脚交视频在线 | 日韩午夜激情网 | 久这里只有精品国产66热99 | 日韩欧美亚洲国产另类 | 国产极品美女在线观看网站 | 国产高清精品一区二区不卡 | 欧美高清视频www夜 国产在线ts人妖 | 久热国产vs视频 | 欧美精品a一级区 | 成人亚洲精品91专区高清 | 91国内揄拍国内精品情侣对白 | 国产日本一区二区三区 | 日本黄页网址在线看免费不卡 | 午夜激情视频 | 国产99精品视频一区二区三区 | 国产精品99精品一区二区 | 自拍伦理视频一区二区三区 | 99热这里只有精品66 | 国产日产欧美一区 | 精品一区二区三区高清 | 久爱成疾在线视频播放 | 国产精彩乱子真实视频 | 欧美日韩在线无吗一区二区三区 | 国产欧美日韩一区二区搜索 | 99久国产精品午夜性色福利 | 人人澡欧美一区 | 美国十次了 | 日韩制服丝袜片中文字幕 | 好吊妞国产欧美日韩免费观 | 高清自在线看 | 亚色在线播放 | 国产日韩簧片在线观看 | 999电影网 | 欧美一级a国产女香蕉在线 日韩系新ww44ww | 亚洲一区二区偷拍第一页 | 亚洲国产韩国欧美在线 | 一级视频亚洲视频在线观看 | 国产精品一区亚洲一区天堂 | 国产欧美精品国产国产专区 | 国产在线精品国偷产拍 | www.色五月 | 国内性爱精品亚洲 | 一进一出又大又粗爽视频 | 99国产精品欧美一区二区三区 | 成年人在线免费观看视频 | 老司机深夜免费福 | 国产精品日本一区二区在线播放 | 永久在线观看免费视频 | 国产高跟鞋丝袜在线观看 | 日本精品不卡视频 | 精品亚洲精品中文字幕乱码 | 欧美日韩一区二区不卡三区 | 国产免费私拍一区二区三区 | 午夜爽片超清 | 欧美日本高清阿v视频在线 97视频专区 | 国产欧美日韩午夜在线观看 | 动漫精品欧美一区二区三 | 亚洲人成小说网站色在线 | 日韩欧美一二三 | 日韩一区二区在线 | 国产在线99| 97国产婷婷综合在线视 | 手机看片国产欧美日韩 | 日本精品精品精品线视频 | 国产免费a视频网站在线观看 | 欧洲精品色 | 日本在线看片免费人成视频 | 成人午夜看黄在线尤物成人 | 最新热门日韩电影 | 玖玖手机在线超级视频观看 | 国产亚洲日韩欧美在线播放 | 国产欧美日本综合在线 | 欧美精品成人一区二区三区影院 | 777米奇影院影音先锋 | 亚洲国产日韩在线人高清au | 欧美高清在线视频在线99精品 | 国精产品一品二品国精品69xx | 永远免费观看 | 国产高清女主播 | 大肉大捧一进一出69xx | 国产网曝门亚洲综合在线 | 337p日本大胆欧美人 | 欧美色欧美亚洲高清在线视 | 欧美韩国电影免费在线观看 | 免费成人高清在线视频 | 成人欧美一区二区三区1314 | 乱伦国产精品日本 | 国产丝袜控视频在线观看 | 亚洲综合在线一 | 国产精品videosse | 国产第37页屁屁影院 | 国产偷国产偷亚洲高清人 | 亚洲日韩国产第一成人 | 办公室风雨未删减 | 国产亚洲欧美一区二区 | 暴躁少女csgo视频 | 息与子猛烈交尾在线播放 | 国产又滑又嫩又白 | 韩国一区二区三区日 | 国产欧美日韩第一页 | 国产人成| 国产精品亚洲精品不卡 | 国产自偷酒店在线观看 | 九九九热在线精品免费全部 | 亚洲伊人精品国产91综合 | 欧美日韩第一区二区三区 | 日本在线播放一区二区三区 | 91高清视频| 在线观看高清三级综合 | 亚洲国产精品福利片在线观看 | 日韩欧美tv一区二区在线观看 | 国产精品亚洲视频在线观看 | 欧美高清一区二区三区不卡视频 | 免费变态视频网站网址不卡 | 在线一区 | 国产女人体一区二区三区 | 国产人妖专区在线视频一区 | 精品日产一区二 | 欧美日韩aa一级视频 | 精品国内一区二区三区免费 | 最好看中文字幕国语电影 | 97国产综合色产在线视频 | 精品一区二区三区在线观看视频 | 高清在线午夜一区二区亚洲 | 国产区日韩精品一区二区三区 | 亚洲jizzjⅰzz妇女 | 精品91自产拍| 精品国内一区二区三区免费 | 午夜成人免费y在线观看 | 99精品全国免费观看视频 | 神马光棍影院 | 欧美一区二区三区播放 | 国产一级a毛一级a看 | 国产普通话漏脸在线观看 | 豆奶app官方网站 | 日本aⅴ精品一区二区三区日 | 日本在线综合一区二区三区 | 国产一区二区三区免费视频 | 国产日韩免费视 | 日本黄一级日本黄二级 | 亚洲无线一二三四区手机 | 国产最新亚洲精品 | 日韩专区一中文字目一区二区 | 国产日韩欧美911 | 欧美亚洲日韩一区二区三区中文 | 56prom精品视频在放免费 | 国产亚洲欧美日韩在线三区 | 国产日韩欧美精品 | 老司机成人亚洲精品影院 | 日韩国产欧美精品综合二区 | 国产一二三区精品免費資訊 | 欧美日韩国产 | 日韩欧美色射高清 | 亚洲欧美国产精品制服 | 国产精品高清偷窥盗摄 | 国产乱ⅴ一区二区三区 | 日韩一区二区三区不卡免 | 国产激情视频 | 欧洲成人r| 国产一区二区三区中文在线 | 亚洲综合中文 | 欧洲变态另类zozo | 在线精品国产一区二区 | 日韩天堂在线专区 | 凹凸国产熟女精品 | 欧美特黄特色三级视频在线观看 | 日韩极品精品一区二区三区 | 国产精品你懂得 | 精品国产插穴精品网站日本 | 日韩在线视频二 | 亚洲国产精品一区二区三区 | 成年人视频在线播放 | 国内欧美日韩在线 | 国产丁香婷婷在线亚洲视频 | 国产一级a在线观看免费 | 国产又色 | 国产亚洲一区激情小说 | 热映电影票房 | 国产巨作在线无遮 | 国产又色又爽又刺激在线播放 | 国产精品美妞一区二区三区 | 日本一区免费在线 | 精品性高朝 | 国产又粗又硬又长又爽 | 欧美香蕉大胸在线视频观看 | 精品欧美日韩一区二区三区 | 免费精品一区二区三区第35 | 国产女同一区二区在线 | 国产高清一区二区视频 | 国产高清在线精品一区不卡 | 在线观看国产日韩欧美 | 精品欧美视频在线播放不卡 | 91超精品 | 精品国产免费人成电影在线观 | 欧美日韩国产无限码一区 | 国内精品自产拍在线观看 | 欧美日韩国产另类激情一区 | 五十路熟女久 | 午夜视频在线观看国产 | 在线视频一区二区三区三区不卡 | 免费人成网站在线观看欧美 | 成全影视| 欧美日韩国产欧美 | 精品日韩欧 | 国产一级特黄aa大片线观看 | 国产免费人成视频在线观看 | 欧美va免费高清在线观看 | 国产亚洲欧美日韩高清专区 | 午夜网站在线观看www | 国产在线videos | 成人国产精品一区二区在线观看 | 欧美国产激情一区综合 | 被黑人猛cao | 亚洲日本中文字幕一 | 最近高清中文在线字幕在线观看 | 国产精品第一页在线观看 | 欧美午夜理伦三级 | 日韩高清在线亚洲 | 国产欧美一成人不卡视频 | 国产99久60在线视频 | 亚洲精品v天堂 | 男人的j| 在线日本高清不卡免费v | 91网站在线播放 | 国产激情自拍亚洲精品国产精品精 | 欧美日韩国产青椒午夜剧场 | 日韩欧美 | 最近日本电影免费观看全集 | 国产一区二区不 | 欧美午夜成午夜成年片在线观看 | 欧美日韩韩高清在线不卡 | 青青国产揄拍在线观看 | 欧美国产一区视频在线观看 | 欧美高清免费精品国产自 | 国产91蜜臀精品对白在线播放 | 国产无人区一区二区三区 | 99视频.com| 国产一区二区三区成人欧美日韩 | 国产精品香蕉夜间视频免费播放 | 国产一级大片免费 | 亚洲伦理精品一区二区三区 | 日本中文字幕一区在线观看 | 精品国产欧美另类一区 | 992t| 国产3级在线观看 | 中文字幕一区二区三区免费看 | 国产精品亚洲а∨天堂网 | 精品国产一区二区三区免费 | 好吊妞在线新免费视频 | 国产美女一区二区在线观看 | 国产精品香蕉夜间视频免费播放 | 97超频精品视频在线观看 | 亚洲性影院在线看 | 亚洲第一性网 | 日本一区二区三区视频b | 国产在线ts人妖 | 精品三级 | 国产网站免费视频 | 吃大瓜吃瓜 | 日本一区免费电影 | 国产美女视频免费 | 北京国贸大酒店张津 | 日韩精品99国产国产精 | 国产免费一区二区三区vr | 国产三区四区五 | 国产中老年妇女精品 | 国产普通话漏脸在线观看 | 国产欧美日韩综合港台 | 日韩精品一区二区三线 | 羞羞影院午夜男女爽爽免费 | 国产一级做a爰片在线 | 日产欧美电影一区二区三区 | 国产精品外围在线观看 | 久艹色色青青草原网站 | 午夜成人影院网站18进 | 国产婷婷久 | 日韩xxx免费视频 | 永久免费播放 | 日本日韩精品 | 女人一区二区视频免费 | 片免费看 | 国产精品丝袜黑 | 日韩一级大片国产 | 亚洲国产的精品太乱码一区二区 | 欧美日韩精品国产一区二区 | 96在线视频精品 | 欧美日韩国产精品自在自线 | 在线一区二区美欧视频 | 国产午夜福利院757视频 | 欧美v国产v亚洲v | 国产精品国色综 | 国产精品99五月天 | 国产美女自卫 | 国产又大| 韩日精品视频 | 国产综合日韩伦理 | 欧美视频一区免费精品 | 亚洲香蕉综合在人在线视看 | 国产对白国语对白 | 精品国语任你躁 | 自拍偷拍欧美图片 | 国产6699视频在线观看 | 韩国非常大度的电影原声 | 国产精品激情综合 | 精品玖玖玖视频在线观看 | 亚洲熟女一 | 国产日韩一二三四区 | 日本一区二区三区四区视频 | 欧美日韩国产无线码一区 | 成人字幕网视频在线观看 | 国产资源在线视 | 国产探极品在线观看观看 | 国产欧美一区二区三区精品 | 欧美午夜一区二区三区 | 亚洲最大 | 小sb几天没做又欠ch | 亚洲精品沙发午睡系列 | 国产免费一区二区三区视频 | 在线看片免费人成视久网 | 看h片的网站 | 国产大片好看免费 | 国产伦精一品二品三品 | 热99r| 中文天堂最新版资源 | 欧美特级特黄aa | 免费无毒a网站在线观看 | 97色轮| 欧美一级a做片性视频 | 日本免费看黄 | 国产精品密蕾丝视频下载 | 97国产亚洲精品第一综合 | 欧美另类国产精品一区二区在线 | 欧美日产国产韩国 | 国产高清又黄又爽又刺激视频 | 99亚洲综合精品 | 国产久热香 | 成人3d动漫一区二区三区91 | 午夜亚洲一区二区福 | 日韩欧美天堂一区二区三区 | 欧美日韩精品一区在线播放 | 国产在线观看色窝网 | 成人影院| 国产日韩欧美丝袜另类视频 | 亚洲精品国产福利片 | 国产视频精品分类 | 在线观看视频导 | 欧美日韩不卡中文字幕在线 | 99re在线这 | 日韩欧美精品一区二区在 | 日韩中文字幕第二页 | 1024手机看片国产日韩欧美 | 国产日韩精品一级二级 | 九一看片| 涩色亚洲激情第二页 | 精品一区二区三区3d动漫 | 成年网站免费入口 | 动漫无遮 | 海角国精产品一区一区三区糖心 | 午夜伦理电影网电影午夜伦理 | 最好看的中文2025 | 精品欧乱仑在线 | 国产一区视频在线观看 | 中文字幕日韩wm二在线看 | 欧美激情人成视频在线观看 | 日本福利 | 日韩免费福利试看3分钟 | 国产亚洲午夜影视在线观看 | 欧美人与动ⅹxxxzooz | 国产在线精品一区二区在线观看 | 亚洲人护士毛茸茸 | 天堂亚洲日韩专二区 | 99国产精品99久 | 国产小视频免费在线观看 | 日韩成人免播放器在线视频 | 美女诱惑中文一区二区三区 | 欧美一级高清视频在线播放 | 欧美疯狂party | 九九视频在线免费观看 | 337人体做爰大胆视频 | 午夜欧美福利 | 日韩免费精品一区二区三区 | 亚洲日韩成人精品不卡在线 | 男女做羞羞的事情网站在线观看 | 爱如潮水视频在线观看 | 国产精品亚洲va | 国产精品网友自拍 | 成人福利 | 亚洲欧美日韩国产综合在线看片 | 又粗又黄又猛又爽大片免费 | 国产玖玖玖精 | 日韩精品搭讪在线视频播放 | 国产高清精品二区 |