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

金喜正规买球

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已經連接。現在我們需要通過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: 關于移動開發,這些產品你可以關注>>
關于移動開發的最新資訊和產品推薦,請<>!
掃碼咨詢


添加微信 立即咨詢

電話咨詢

客服熱線
023-68661681

TOP
国产中文成人精品小说 | 日韩中文字幕高清一区 | 一区二区三区高清视频 | 91影视永久福利免费观 | 精精国产xxxx视频在线播放 | 女子初尝黑人巨嗷嗷叫 | 综合五月天 | 日本大胆一区二区三区 | 国产乱子伦高清对白 | 国精产品一品二品国精品69xx | 92午夜福利1000集在线看 | 欧美牛逼aa| 国内女人喷潮完整视频 | 欧美女优在线观看br | 日韩伦理一区二区精品视频 | 成人免费观看做爰视频胸大 | 亚洲欧美专区 | 十九岁中国电影在线观看免费 | 日日插人人插天天插 | 性xxxx18免 | 国产aⅴ | 午夜福利在线观看 | 亚洲愉拍国产自免费 | 国产午夜福利精品一区二区三区 | 歐美性猛交xxxx亂大交3 | 国产h视频在线观看免费 | 天堂在线视频网站 | 精品欧美在| 日本强伦姧人 | 国产小视频在线观看免费 | 婷婷综合激情五月中文字幕 | 2025最新在线观影网站 | 最近中文字幕在 | 国产精品露脸国语对白99 | 夜夜爽一区二区三区精品 | 欧美综合亚洲 | 精品午夜福利在线视在亚洲 | 日韩中文字幕精品视频在线 | 午夜免费福 | 欧美日韩中文字幕在线一区二区 | 欧美a级大片 | 国产精品午夜看片 | 女同精品一区二区 | 国产精品外围在线观看 | 国产精品高清全国免费观看 | 国产超级va在线播放 | 国产在线精品一区二区在线观看 | 国产亚洲精品资源在 | 亚洲熟女乱综合一区 | 精品国产污| 第一福利精品500在线导航 | 最近免费中文mv在线字幕 | 善良的老师中文字 | 国产美女一级a视频欧洲 | а√天堂地址在线网 | 午夜男女爽爽爽免费播放 | 国产精品视频第一区二区三区 | 免费99精品 | 三级三级三级a级全黄三 | 国产精品免费精品自在线观看 | 国产精品视频全国免费观看 | 亚洲国产精品综合色在线 | 日本午夜免费啪视频 | 中文天堂最新版资源 | 在线精品欧 | 中文在线中文资源 | 日本精品专区在线 | 国产日产韩国精品视频 | 国产免费一区二区视频 | 中文字幕一区二区三区不卡 | 青苹果影院 | 精精国产xxxx视频在线播放 | 日本动漫精品一区二区三区 | 日本高清中文字幕在线 | 亚洲欧美日韩一区高清中文字幕 | 91探花国产 | 国产免费直播在线观看视频 | 天天综合网天天做天天受 | 成人午夜视频精品一 | 国产精成人品日日拍夜夜免费 | 99视频精品国 | 日本精品无人区1区2区3区 | 老子午夜伦理不卡一级电影 | 国产精品自产精品在线观看 | 免费手机在线看片 | 国产日韩免费视 | 好看的高清电影大全 | 国产视频亚洲 | 亚洲jizz | 亚洲精品动漫一区二区三区在线 | 天天看片国产精品 | 精品伦精品一区二区三区视 | 中国在线观看免费国语版 | 国产婷婷一区二区在线观看 | 亚洲色大成 | 国产欧美日韩夜夜爽人人 | 国产精品va在线观看 | 国产欧美一区二区 | 亚洲国产砖一线二线 | 日本在线播放一区二区三区 | 91极品看片 | 欧美日韩欧 | 国产粗语刺激对白ⅹxx | 好看的中文字幕aⅴ在线视频 | 俄罗斯美女真人性做爰 | 国产精品一区二区久 | 国产高清在线精品二区一 | 人伦小说视频在线 | 亚洲欧美日韩中文字幕在线不卡 | 国产欧美精品国产国产专区 | 国产一级一片免费播放放a 91香蕉成人app | 日本中文一区二 | 亚洲一区自拍视 | 日韩专区亚洲精品欧美专区 | 国产真实迷奷 | 国产欧美综合精品一区二区 | 青青国产在线观看 | 三年片在| 精品国精品国产自在久国产应用 | 国产亚洲精品成人 | 国产精品偷窥熟女精品视频 | 一扒二脱三插片在 | 成人国产一区二区 | 国产精品va在线观看蜜臀 | 在线播放亚洲精品 | 区三区在线 | 亚洲午夜福利 | 伊人网视频 | 最新中文字幕第一页 | 亚洲视频 | 免费人成在线观看 | 2025国产精品偷窥盗摄 | 亚洲免费黄| 国产精品蜜桃 | 亚洲国内自拍欧美一区二区三区 | 国产精品一品道加勒比 | 欧美另类视频在线观看 | 国产高清一区二区三区视频 | 色一情一伦一区二区三 | 亚洲日本一区二区在线观看 | 亚洲日本一区二区 | 成年男人午夜片免费观看 | 国产区日韩精品一区二区三区 | 三级在线国产 | 中文字幕在线免费专区 | 欧美亚洲| 韩日国产精品一区二区三区 | 日韩一区二区三区免费网站 | 51精品国产人成在线观看 | 精品国产第一页 | 午夜不卡影| 亚洲一区二区三区高清在线播放 | 日韩视频中文字幕 | 人国产在线观看不卡片 | 亚洲亚洲人成网站77777 | 国产精品大战 | 欧美一区日韩二区在线观看 | 亚洲人成色7777在线观看 | 日韩高清在线播放 | 亚洲色精品三区二区一区 | 亚洲精品沙发午睡系列 | 天美麻花果冻视频大全 | 加勒比he | 中文字幕v人| 在线观看亚洲中文字幕 | 国产欧美日本亚洲精品五区 | 亚洲国产99在线精品一区 | 一级一黄免费视频在线看 | 成人国产精品中文字幕 | 国产精品一区二区在线精品 | 日本高清视频免 | 欧美精品综合一区二区三区 | 久热在线精品视频观看 | 美女视频免费观看网站黄 | 免费人成年短视频免费网站 | 国产一区二区三区不卡在线看 | 亚洲精品免费 | 丰满老熟好大bbb | а√天堂资源官网在线资源 | 亚洲午夜理论片在线观看 | 香蕉亚洲精品网站国产一二三四 | 欧美人与日本人xx在线视频 | 视频区国产图片区小说区 | 国产微信高清小视频在线播放 | 免费一区二区三区视频 | 第一福利社区1024 | 中国凸偷窥xxxx自由视频 | 97涩涩| 国产一区 | 国产91精品一 | 国产乱伦免 | 国产欧美精品一区二区三区四 | 日本三级在线视频 | 精品一区二区三区国产视频 | 大伊香蕉精品一区在线 | 网站资源多午夜激情影院 | 在线精品国| 亚洲精品免费日日日夜夜夜夜 | 真实国产精品vr专区 | 欧洲精品视频一二三区视频 | 噜噜噜在线视频免费观看 | 最新电影电视剧观看 | 特黄a三级三级三级视频 | 国产一产二产三精华液 | 亚洲精品伦理一区二区三区青春 | 日韩免费在线观看性生活视频 | 欧美.日韩.日本中亚网站 | 中文在线欧美亚洲制服 | 国产高清乱码又大又圆 | 亚洲国产区男 | 黄动漫在| 国产福利不卡视频在免费 | 黑人巨大精品欧美一区二区免费 | 在线观看国产一区二区三区 | 欧美日韩一区不卡 | 色综合婷婷在线观看66 | 成人免费xxx在线观看 | 日韩一区二区四区高清免费 | 亚洲码国| 欧美午夜在线观看 | 天天射天 | 为您提供国产成 | 国产欧美一区二区精品久 | 欧美日本韩国一 | 91九色老熟女免国 | 好吊色欧美一区二区三区视频 | 多人性战交疯狂派对 | 国产伦理一区 | 三区在线播放 | 起碰97在线视频国产 | 久中文字幕中文字幕亚洲无线 | 免费国产一级a | 永远免费观看 | 中文字幕第一页 | 午夜福利电影 | 黑人巨大精品欧美一区二区 | 中文字幕亚洲一区二区三区 | 国产v综合v亚洲欧美大片 | 国产一区视频一区欧美 | 亚洲成a人片在线观看www流畅 | 三级三级三级a级全黄三电影 | 国产偷v国产偷v | 国产精美视频在线观看 | 精品一区二区三区的国产在线观 | 91社影院在线观看 | 日韩一区二区三区四区中文字幕 | 咻咻漫画在线观看 | 国产午夜亚洲精品不卡在线观看 | 欧美日韩视频在线观看第一区 | 三年片大全在线观看 | 日本中文字幕乱码 | 日本三级理论一区二区三区 | 99久高清| 欧美一级高清片国产特黄大 | 国产乱偷精品视频a人人澡 日韩免费在线观看视频 | 国产日韩欧美第二页 | 精品国精品国产国产 | 国产国产人免费人成成免视频 | 国产精品亚洲а∨无 | 亚洲日韩乱码中文字幕 | 国产婷婷综合在线精品尤物 | 91精品国产品国语在线 | 欧美a级情欲片手机在线播放 | 亚洲开心婷婷中文字幕 | 99精品一区二区三区免费视频 | 亚洲视频高清不卡在线观看 | 欲香欲色天 | 日韩精品一区二区三线 | 激情五月天深爱网 | 日韩本免费一 | 久热国产vs视频在线观看 | 亚洲精品理论电影在线观看 | 91社区国产在线播放 | 91精品国产人成网站 | 精品成人18成人免费视频 | 91视频福利| 国产男生夜间福利免费网站 | 第一页欧日韩在线视频 | 国内精品日本和韩国免费不卡 | 国产亚洲中文一区二区三区 | 免vip免费观看热播电 | 国产一国产二国产三国产 | 未满十八勿入网站 | 国产特级婬片免费看 | 日本国产性爱观看视频 | 免费网站看v片在线爱的影院 | 午夜性爽一区二区三区 | 亚洲高清无一区二区三区四区 | 国产激情视频网站 | yin荡护士揉捏乱p办公室视 | 都市激情亚| 欧美国产综合欧美视频 | 国产美女一级做视须爱 | 日韩欧美一本书道一区二区 | 一级理论片免费观看在线 | 国产在线91 | 国产亚洲国际精品福利 | 亚洲综合欧美日韩国产一区二区桃 | 国产精品17p | 芙宁娜裸身被羞羞漫画 | 日韩欧美精品综合一区二区三 | 国产一区二区免费视频 | 最近中文字幕 | 欧美不卡在线 | 国产又大又硬又粗视频 | 韩日国产精品一区二区三区 | 区二区三区蜜芽 | 国产一区二区视频 | 国产精品亲子乱子伦xxxx | 亚洲欧美激情精品一区二区 | 级欧美一级一级国产 | 午夜免费观看福利片 | 三级高清精品国产 | 亚洲精品国产va在线观看天堂 | 50岁退休| 日韩欧美一区二区不卡看片 | 亚洲一区在线视频 | 欧美一级一区二区电影 | 视频在线华人精品草 | 中文字幕永久在线第38 | 香蕉免费一区二区三区 | 2025最新免费电影 | 中文天堂| 草莓视频污污版 | 少女哔哩 | 久视频在线 | 欧美极品另类ⅴideosde | 好男人网官网在线观看2025 | 亚洲人成在线中文字幕 | 国产国产人免费视频成 | 中文成人| 亚洲成?v人片在线观看福利 | 91福利国产在线在线播放 | 亚洲福利中文字幕在线网址 | 涩涩视频午夜福利一区二区 | 窝窝午夜理论片影院 | 亚洲精品乱码在线观看 | 精品国产欧美一区二区 | 最新国产一区二区三区在线 | 51精产国品一二三产区区 | www.五月婷 | 飘雪免费手机全集在线观看 | 日韩精品在线视频直播 | 日本三级理论一区二区三区 | 亚洲大片精品永久免费看网站 | 亚洲熟女乱综合一区二区 | 一级女性全黄生活片免费 | 欧美日韩国产免费一区二 | 日韩免费一区二区三区高清 | 国产精品自在线免费 | 九九精品视频国产 | 国产大片b站免费观看推荐 国产91尤物在线观看互 | 另类视频一区二区三区 | 设看到很多欧美日韩一区二区综 | 在线综合亚洲欧洲综合网站 | 日韩精品一区二区三线 | 香蕉伊蕉伊中文视频在线 | а√天堂资源官网在线资源 | 精品国产男人的天 | 亚洲aⅴ无一区二区三区 | 羞羞视频下载 | www.尤物在线 | 精品成人18成人免费视频 | 在线点播亚洲日韩国产欧美 | 99久国产精品午夜性色福利 | 亚洲欧美中文字幕在线观看 | 日本一区二区三区视频在线 | 日本高清一二三不卡区 | 欧美性受xxxx黑人xyx性爽 | 热映电影票房 | 91最新精品视频在线 | 国产精品一 | 海量资源每 | 欧洲一级大黄大 | 免费人成网站视频在线观看国内 | 香港午夜三级a三级高清观看 | 精品视频高 | 午夜欧美视频在线 | 色色www| 国产综合精品一区二区 | 欧美高清| 免费高清影视资源观看 | 久色资源免费的资源站 | 免费人成视频在线播放视频 | 99一区二区三区国产热视频在线 | 亚洲欧美国产va | 国产乱子伦农村叉叉叉 | 中文字幕影片免费在线观看 | 欧美另类吹潮 | 国产精品一区不卡在线观看 | 水蜜桃国产在线观看免费视频 | 国产精品手机在线 | 国产精品一区二区三区 | 欧美日韩国产色综合一二三四 | 国产精品亚洲精品日韩已满 | 日韩中文字幕在线免费观看 | 中文字幕无线免费 | 欧美又大粗又爽又黄大片视频 | 国产中文字幕不卡在线观看 | 国产综合精品五月天喷水 | 国产精品一区二区三区四区五区 | 国产精品三p一区二区视频 h片在线播放免费 | 欧美亚洲日韩国产人成在线播放 | 国产精品无内丝袜高跟鞋 | 亚洲精品在线免费观看 | 看日韩精品视频在线观看 | 欧美三级在线播放 | 亚洲日韩中文在线精品第一 | 日本精品一区二区三区 | 欧美精产国品一二三类产品特点 | 日韩高清码中文字幕日韩 | 亚洲а∨天堂在线网站 | 小姨子在旁边差点被看到 | αv天堂在线观看免费αⅴ 尤物视频 | 欧美一区二区三区四区国产另类 | 国产精品偷伦视频观看免费 | 亚洲+欧洲+日本+国产 | 国产女人喷潮视频在线观看 | 亚洲国产中文字幕在线观看 | 日韩亚洲欧美高清在线观看 | 国精产品一区二区三区四区糖心 | 在线a亚洲视频播放在线观看 | 欧美偷窥清纯综合图区 | 免费电视剧大全 | 国产午夜福利短视频在线观看 | 亚洲v中文在线播放免费 | 频精品99 | 亚洲一二三四中文字幕 | 国产99视频精品免费视 | 午夜性影院在线观看视频播放 | 2025国产亚洲日韩在线 | 国产99视频精品免费专区 | 国产一区二区三区高清在线观看 | 中文字幕高清在线免费播放 | 在线观看视频导 | 国产成年精品高清在线观看91 | 国产精品日韩专区第一页 | 免费+国产在线观看 | 中文天堂最新版资源 | 欧美精品亚洲日韩aⅴ | 国产在线观看一级二级三级 | 热播电视剧大全 | 日本中文字幕在线观看 | 国产免费一区二区三区在线观看 | 亚洲一区高清 | 天天看片高| 老子影院午夜伦不卡 | 一区二区三区精品视频免费播放 | 三年片最新电影免费观看 | 女同另类一区二区三区 | 亚洲人ⅴsaⅴ国产精品 | 奇米精品视频一区二区三区 | 粗大的内捧 | 亚洲人在线观看影院 | 企业档案| 国产精品一区99 | 欧美日韩精品久 | 欧美精品成人a在线观看 | 欧美mv亚洲mv在线天堂 | 国产在线观看色免費資訊 | 2025国产精品自产拍在线观看 | 国产视频一区在线观看 | 亚洲高清一区二区三区四区 | 国产精品日韩精 | 亚洲va在线观看日本 | 6080神| 日韩经典欧美 | 亚洲午夜成人va在线 | 伊人成年网站综合网 | 亚洲精品宾馆在线精品酒店 | 日本天堂天v在线播放 | 91成人国产网站在线观看 | 国产精品国色 | 看片免费人成视频 | 亚洲欧美另类在线视频 | 国产欧美在线一区二区三区 | 日本亚洲一区二区 | 免费在线观看 | 国产精品成人aaaa网站女吊丝 | 三年片在线观看免费观看大全 | 国产精品思思在线 | 91久色视| 老师裸露胸免 | 国产91尤物中文在线 | 欧美视频人人干人人 | 亚洲精品国自产拍在线观看 | 日韩亚洲欧美一区噜噜噜 | 女人与公驹交酡全过程 | 国内自拍一二三四2025 | 激情五月婷婷丁香六月 | 五月激情丁香婷婷综合网 | 国产在线观看一级二级三级 | 麻花豆传媒剧 | 人在线观看青青 | 伊人大相蕉在线看青青 | 老色鬼在线精品视频 | 在线亚洲| 亚洲中文字幕a | 日韩亚洲人成影院 | 欧美日韩精 | 国产模特精品私拍在线 | 日日摸处处碰夜夜爽 | 精品国产91乱码一区二区三区 | 国产欧美日韩va另类在线播放 | 亚洲人成在线影院 | 色吊丝中文字幕一区二区三区 | 亚州图片 | 日本中文字幕电影 | 深夜爽爽动态图无遮无挡 | 超91精品手机国产 | 99视频精品全部品全正 | 国产精品午夜爽爽爽免费 | 国产片免费 | 中文字字幕在线精品乱码高清 | 国产老熟女狂 | 乱码一码二码三码四码狼人 | 国产精品成人 | 欧美bb | 国产福利在线观看永久免费 | 国产资源精品一区二区免费 | 国产免费人成视频在线观看播放 | 亚洲高清中文 | 欧美超高清xxxhd | 日韩成全视频观看免费观看高清 | 亚洲三级在线观看 | 韩国福利一区 | 国产精品观看 | 亚洲综合一区三区 | 欧美综合自拍亚洲综合 | 国产哟一区二区三区视频在线看 | 国产专区免费资源网站 | 国产不卡在线观看视频 | 人人添人人 | 国产中文另类二区 | 在线视频一区二区三区三区不卡 | 在线中文字幕日韩 | 正在播放一区二区 | 中文字幕精品视频在线观看 | 国产又色又爽又黄刺激的影视 | 天美传媒果冻传媒国产日本 | 亚洲成l人在线观看线路 | 日产精品卡2卡3卡4卡免费 | 日本高清不卡在线中文字幕 | 国产精品三级一区二区 | 亚洲一区国产日韩午夜在线观看 | 欧美色欧洲免费无线码 | 亚洲综合欧美日韩国产一区二区桃 | 九九免费福利精品视频 | 欧美日韩精品一区二区在线观看 | 丰满的女房东在线观看6 | aaa午夜级特黄日本大片 | 区二区视频免费看 | 亚洲国产一区二区三区a毛 国产美女淫秽一区二区三区 | 亚洲精品国产精品乱码不卡√ | 麻花传md0174苏蜜清歌 | 成年动漫h视频在线观看 | 7799精彩视频天天看网站 | 日本免码va免费观看 | 大陆国语 | 丝袜美腿一区二区三区 | 国产第1页| 日韩欧美卡一卡二卡新区 | 国产日韩精品欧美一区色 | 在线观看的资 | 午夜色大片在线观看 | 欧美国产精品va在线观看 | 男女午夜视频在线观 | 国产精品欧美亚洲 | 成年男人午夜片免费观看 | 亚洲欧美国产日产综合不卡 | 欧美一区二区三区四区婷婷 | 一个人看的www视频免 | 国产全部视频在线播放 | 亚洲aⅴ永久无 | 日韩一区精品在线观看 | a级全黄试看30分钟gif动图 | 在线一区二区三区中文字幕 | 中文字幕一区二区不卡 | a级粗大硬长爽猛视频免费 视频二区日韩 | 亚洲熟女精品中文字幕 | 成人三级视频在线观看不卡 | 国产乱码精品一区二区三区卡 | 亚洲一区二区影视 | 欧美日韩成人一区二区三区 | 亚洲欧美国产日韩精品 | 天美传媒、91制片厂、天美传媒 | 日本免费一区二区视频 | 日韩欧美亚洲一区精选 | 国产精品喷水 | 国产哟一区二区三区视频在线看 | 不卡视频一区二区 | 精品国产高清免费在线观看 | 国产精品女同一区二区在线 | 色吊丝中文字幕一区二区三区 | 人在线成视频 | 星辰影院 | 老汉色影院首页 | 97碰碰碰| 村长扶着小萍的腰猛的挺进 | 夜夜未满十八勿进的爽爽影院 | 国产婬妇視频网站 | 911亚洲 | 最新一区二区三区免费看 | 午夜日韩丝袜美女视频网站 | 2025国产激情视频在线观看 | 精品一区二区三区免费观看 | 色屁屁草草影 | 只有精品首页 | 欧美激情在线精品video | 日本中文字幕亚洲东 | 日韩综合一二三区视 | 全网热播最新电影电视剧 | 五月天激情综合网 | 男人本色国产在线综合 | 青青青国产爽爽视频免费观看 | 国产在线观看一区 | 中文字幕日韩 | 欧美高清精品一区二区 | 亚洲美女又黄又爽在线观看 | 又刺激视频| 国产亚洲aⅴ在线电影 | 永久亚洲成a人片777777 | a级国产乱理伦片在线观看al | 日韩精品欧美亚洲高清有无 | 国产激情视频在线观看 | 国亚洲一厂区二厂区三厂区 | 7788电影网| 日本成熟丰满老妇xxxx | 国产精品自拍视频合集 | 国产福利高颜 | 日产中文字幕在线精品一区 | 桃花在线观看视频播放 | 视频观看中文 | 欧美日韩在线观 | 91精品视频在线免费观看 | 涩色亚洲激情第二页 | 午夜激情视频三区在线 | 蜜桃臀aⅴ精品一 | 亚洲综合日韩精品欧美综合区 | 日本sm | 国产精品不卡在线观看的a站 | 欧美韩日二三在 | 国产在线午夜不卡精品影院 | 亚洲一区二区三区不卡视频 | 黄页免费在线 | 国产精品人娇在线内谢 | 国产亚洲福利日本一区二区 | 日本视频在线观看不卡高清免费 | 国产羞羞又硬又粗又长又大 | 精品国产免费人成电影在线看 | 福利吧导航 | 亚洲第一影院中文字幕 | 91丝袜精品诱惑在线观看 | 草莓视频污污版 | 国产亚洲欧洲精品一区二区三区 | 亚洲精成9 | 国产精品va在线播放我和闺蜜 | 一二三区在线观看 | 日韩国产 | 国产一级a爱片 | 91精品国产免费青青碰在线 | 在线视频一区二区三区 | 91极品尤物在线观看 | 亚洲中文字幕30页 | 日本最新免费二区 | 日韩精品在线播放 | 日韩欧美国产一区二区三 | 无颜之月1~5 | 红杏视频打开页 | 亚洲二区在线观看 | 国产公开免费人成视频 | 亚洲视频在线观 | 欧美三根一起进三p | 国产乱码精品一区 | 一区二区中文字幕在线 | 亚洲另内精品 | 成人精品一区二区三四 | 日韩一区二区三区免费视频 | 尹人香蕉久 | 国产丝袜控视频在线观看 | aaaaa级少 | 中文天堂资源在线www | 精品国内一区二区三区免费视频 | 亚洲国产的精品太乱码一区二区 | 国内精品在线一区二区 | 国产欧美精品一区二区三区 | 亚洲第一视频 | 最新69成人国产精品视频免费 | 九九热精品在线视频观看 | 日本全部一级视频 | 成人a视频高清 | 欧美日韩亚洲国产一 | 中文字幕无吗热视频 | 国产不卡高清在线观看视频 | 高清影视在线 | 99这里都是精品 | 欧美国产精品免费观看 | 亚洲精品偷 | 国产精品一区二区在线精品 | 国产在线视频一区二区三区 | 五月综合激情婷婷六月色窝 | 亚洲变态欧美另类精品 | 国色一卡2卡二卡4卡乱码 | 日本亚洲欧美国产电影在线观看 | 欧美人兽一区 | 国产激情电影综合在线看 | 国产乱理伦片在线观看夜 | 香港三级日本三级韩国三级 | 国产成本人三级在 | 亚洲偷自拍拍综合网 | 亚洲欧美日韩中文二区 | 国产每日更 | 国产人成午夜免电影费观看 | 国产精品福利资源在线 | 亚洲午夜福利院在线观看 | 影音先锋教师波 | 2025年全裸 | 二区视频在线观看 | 五月天婷婷网亚洲综合在线 | 亚洲日韩欧美一区二区在线 | 成年网站拍拍拍免费播放 | 一区二区三区亚洲高清 | 亚洲一区二区三区首页 | 国产在线精品免费一区二区三区 | 国产精品揄拍100视频 | 免费一级中文字 | 手机看片1204日韩 | 亚洲精品福利在线观看 | 日本阿v免费观看网站 | 免费国产va在线观看中文 | 大地影院mv高清在线观看免费 | 日韩亚洲欧美精品性爱 | 国产灌醉极品在线观看 | 视频在线观看不卡 | 日本伊人精品一区二区三区 | 综合狠狠| 亚洲视频高清不卡在线观看 | 日本欧美中文字幕精品一区 | 午夜免费视频在线观看 | 国产精品亚洲a∨天堂 | 欧美日韩中文在线视频 | 电视剧热播大 | 免费手机影院 | 国产亚洲一区激情小说 | 国产户外露出在线观看 | 亚洲精品欧美精品日韩精品 | 亚洲日本一区二区三区在线 | 91精品国产品国语在线 | 亚洲欧美在线x视频 | 亚洲区日韩精品中文字暮 | 亚洲的一区二区精品 | 91视频官| 国产特级婬片免费看 | 99在线观看视频免费精品9 | 欧美一区二区电影免费观看 | 好吊色永久免费视频在线观看 | 九九91精品国产 | 国产亚洲一区二区手机在线观看 | 日本中文字幕电影 | 日韩精品国产另类专区 | 久热精品视频在线播放 | 日韩精品极| 成人又黄又爽又色的网站 | 日本精品久 | 欧美激情va永久在线播放 | 第四色伊人 | 欧美日韩综合在线播放 | 中文字幕夫妇交换乱叫 | 国产精品亚洲专 | 国产精品三级在线观看 | 国产伦亲子伦亲子视频观看 | 亚洲人在线观看影院 | 涩涩欧美 | 日本一区二区三 | 最近中文字幕高清字幕在线视频 | 手机电影| 日本素人黑人视频 | 欧美午夜理伦三级在线观看 | 好看的电视 | 伦理电影在线观看 | 欧美国产日韩在线播放成人 | 色依依亚洲一区在线观看 | 在线国产| 国产精品亚洲精品一区二区三区 | 一二三四在线观看免费中文吗中文 | 91免费在线观看 | 在线播放真实国产乱子伦 | 欧美视频在线视频精品 | 亚洲人成小说网站色在线 | 俺来也俺也啪www色 国泰饭店 | 五福临门电视剧免费观看完整 | 国产喷水大秀在线观看2025 | 二区三区爱欲九九 | 国产午夜三级一区二区三 | 国产95在| 午夜私人影院免费体验区 | 97午夜理论 | 欧美不卡一区二区 | 国产日韩高 |