超碰91资源站-超碰97豆花-超碰97人妻-超碰97人人干-超碰97人人香蕉-超碰97天天操-超碰97在线资源站-超碰97资源站共享-超碰97资源站总站-超碰aa在线91-超碰av操-超碰爱爱

半岛外围网上直营

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
利記足球官網(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) 真人boyu·博魚滾球網(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) 最大網上PM娛樂城盤口(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) 正規雷火競技官方買球(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) 雷火競技權威十大網(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) boyu·博魚信譽足球官網(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) 權威188BET足球網(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) 正規188BET足球大全(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) 国产二区三区毛片 | 国产a精品 | 国产成人无码免费看片软 | 91国偷自产中文字幕 | 国产精品亚洲二区在线看 | 国产在线成人 | 国产精品高潮呻吟久久v无码 | 国内免费视频一区二区三区 | 国产av一区二区 | 国产成人短视频在线观看免费 | 国产私伦一区二区三区 | 国产精品欧美日韩在线一区 | 91大神国内精 | 国产aⅴ无码专区久久精品国产 | 国产精品一级a片不卡 | 精品久久精品中文字幕无码 | 波多野结衣国产一区二区在线观看 | 国产毛片特黄毛片老人 | 国产成人午夜无码电影在线观看 | 国产高清天干天天天 | 国产毛片情侣视频 | 国产在线视频一区二区三区 | 国产欧美另类久久久精品丝瓜 | 91久久精一区二区三区大全 | 国产片婬乱一级毛片视频1 国产片婬乱一级毛片丫丫 国产片婬乱一毛片a | 国产操逼视频 | 丰满人妻一区二区三区免费视频 | 爆乳系列无码 | 91久久夜色精品国产九色 | 91性爱视频在线观看 | 3d动漫精品啪啪一区二区免费 | 91福利国产门事件在线观看 | a级毛片高清免费视频 | 国产精品无码久久综合网老 | 国产免费一区二区三区最新 | 国产成人高清成人av片在线看 | 91蜜桃视 | 国产精品v欧美 | 国产成人综合亚洲色就色 | 国产免费一区二区三区最新 | av无码久久 | 国产精品无码久久sm | 91精品国产aⅴ一区二区 | 国产一区二区三区美女 | 国产福利91精品一区 | 白丝超短裙自慰喷水爆白浆 | 国产无码视频在线播放 | av综合网| 成人免费片在线观看国产 | 国产成人午夜视频影院免费观看 | 18禁动漫美女禁处被爆桶出水 | 91po国产在线精品免费 | 国产精品国产三级国产三级 | 国产成人亚洲精品青草天美 | 国产精品成人免费视频99 | 国产精品成人黄色片 | 东京热人妻无码人av | 精品香蕉一区二区三区浪潮 | 精品九九99久久在免费线 | 国产精品一二三四区视频 | 91久久精品在这里色伊人68 | 成人综合久久久 | 精品无码国模私拍视频 | 国产一级一片免费播放 | 99自偷国偷产品一区电影 | 成人三级毛片在线播放 | 精品久久久久久无码中文野结衣 | 国产国语高清在线视频二区 | 白丝爆浆18禁一区二区三区 | 不卡一区二区三区免费视频 | 二区黄色| 高清在线制服亚洲 | 国产成人综合久久精品免费 | 3d无码纯肉动漫在线观看 | 国产午夜精品一区二区 | 国产激情久久亚洲欧美视频在线 | 91精品一区二区网站 | 国产自精品在线 | 二区三区中文字幕 | 91久久人妻无 | 国产高清在线精品一区在线 | 91精品久久久久五月天精品 | 国产高清精品二区 | 国产成年精品高清在线观看91 | 97人妻在线免费视频 | 国产主播一区二区 | 国产成人高级 | 国产精品视 | 国产裸拍裸体视频在线观看 | 国产精品成人va在线观看 | 高清无码中文字幕乱码 | 国产对白叫床清晰在线播放中 | 国产古代三级在线播放 | 国产精品白浆无码流出视频 | 91大片淫黄大片在线天堂 | 国产拍一二三四区在 | 国产av国片精品有毛 | 91国内揄拍国内精品情侣对白 | 国产极品粉嫩馒头一线天图片 | 91久久综合精品国产丝袜长腿 | 91麻豆精品国产高清在线 | 国产一区二区三区乱码 | 国产精品99无码一区二蜜桃 | 成人免费在线观看 | av片在线观看网站免费的 | 911亚洲精品国内自产 | 91国内精品在线 | 国产一区二区高清在线国产综合 | 国产女性精品一区二区三区 | 国产麻豆视频 | av麻豆男人的天堂在线观看 | 国产a久久精品一区二区三区 | 国产无码专区在线播放视频 | 国产日韩欧美精品先锋 | 国产一线久久 | 国产区在线观看视频 | 潮喷大喷水系列无 | 国产精品免费大 | 国产三级毛片在 | 国产成人av在线你懂的 | ww国产内射精品后入国产 | 高清无码在线一区二区 | 国产精品日韩欧美一区二区 | 国产精品亚洲色一色 | 国产精品无码素人福利免费 | 国产日韩乱码精品一区二区 | 国产熟女高潮视频 | 99精品无人区乱 | 91亚洲午夜三级 | 99久久精品国产中国久久 | 囯产精品国产三级国 | 国产野战无套av毛片 | 91精品国产一区二区三区左线 | 国产亚洲欧洲人人网 | 国产福利拍拍拍 | 国产末成年女av片一区二区 | 91精品欧 | 国产亚洲欧美在线观看一区二区 | 护士av无码在线观看 | 国产精品亚洲一区二区在线观看 | 国产高潮美女出白浆在 | 国产人妖熟女 | 国产一区二区三区日本道 | 精品国产sm最大网站起碰 | 国产精品入口麻豆高清 | 2025国自产拍精品免费观看 | 国产内射在线激情一区 | 国产午夜精品精品 | 9191精品国产免费不久久 | 国产欧美成人福利在线播放 | 精品视频一区二区三区不卡 | 91精品国产福利在线观看雪梨 | 国产毛片在线看 | 国产精品无码电影在线观看 | 国产精品熟妇一区二区三区四区 | av毛片高清在线观看 | 国产无套白浆视频在线观看 | av无码专区亚洲avl在线观看 | 国产高清中文字幕欧美 | 国产成人精品日本亚洲成熟 | 国产精品九九久久精品女同 | 国产精品一区二区三区免费视频 | 国产欧美日韩中文字幕第一页 | 国产妇少水多毛多高潮a片小说 | 精品视频一区二区三区不卡 | 国产成人精品免费大全 | 国产91电影厂精品福利片 | 91麻精品国产91久久久久 | 91视频导航| 2025国产精品网站在线播放 | 99久久人人爽亚洲 | 国产精品自拍av | av永久天堂一区二区三区 | 91麻豆人妻春色影视 | 国产成年女人毛片80s网站 | 国产剧情麻豆mv | 国产精品自拍偷无码乱码av | 精品无码国产av一区二区三区 | 成人a级视频在线播放 | 成人午夜男女爽爽影院 | 国产精品成人无码a片免费网址 | 国产白丝无码免费视频 | 国产白丝精品久久av网站 | 国产精品丝袜拍在线观看 | 国产在线视频主播区 | 国产aⅴ精品一区二区果冻 国产aⅴ精品一区二区久久 | 高清av在线短片毛片 | 国产精品日韩在线 | 国产一区二区三区日韩精品欧美 | 国产在线观看一区二区三区 | 国产成人精品国产亚洲欧洲 | 国产精品午夜国产小视频 | 国产成人久久精品毛片 | av毛片久久久久午夜福利hd | 国产精品日韩高清秒播日韩国产欧美 | 韩国免费高清一级毛片性色 | 国产欧美日韩资源在 | 国产美女三级片视频 | 91麻豆精品国产福 | 精品亚洲av无码国产一二区在线 | 国产高清a级毛片视频 | 国产精品午夜福利免费 | 国产亚洲欧美观看在线一区 | 国产精品成人一区二区三区吃奶 | 国产成人综合亚洲无码中字 | av每日更新在线观看 | 国产美女露脸一级毛片 | 国产精品国产成人国产三级 | 国产成人精品999在线观看视频 | 国产精品一区二区无码 | 高清在线亚洲精品国产二区 | 国精一二三区 | 国产在线观看精品香蕉v区 国产在线观看精品一区二区 | 国产91在线免费观看 | 99精品中文字幕在线推荐 | 国产在线无码不卡影视影院 | 国产无套流白浆视频免费 | 国产精品一二三区 | 国产一线天粉嫩馒头极品av | 国产亚洲欧美日韩综合一区二区 | 91麻豆精品国产自产在线观看一 | 国产精品一区二区三免费99精 | a级全黄试看30分钟观看 | 成人午夜福利视频 | 国产精品一区一区三区 | 国产高清在线精品一区不卡 | 国产成人精品免费无码 | 国产精品日本免费视频 | 高清国产亚洲精品自在久久 | 国产三级一二三四五区 | 成人综合色站在线观看 | 国产午夜在线观看免费 | 国产精品一区二区亚瑟不卡 | 国模精品成人片在线播放 | 粉嫩虎白女流水粉色视频 | 国产精品无码制服丝袜 | 国产内射又粗又大又猛 | 国产成人欧美在线视频 | 精品国产一区天天 | 国产精品一区二区宅男宅女 | 3p国产对白刺激 | 国产福利免费视频 | 精品国产美女福到在线不卡 | 国产成人人黄鳝网站视频 | 精品国产丝袜黑色高跟鞋 | 91精品国产免费久久久久久 | 成人午夜福利电影 | 高清无码在线观看亚洲 | 精品国产一级久久 | 国产极品精品无码在线播出 | av高清网址在线观看 | 91福利国产在线在 | 国产欧美日韩在线综合网 | 东京热男人的天堂精品 | 国产综合精品婷婷丁香五月 | 成人无码a区在线观看视频 成人无码h免费动漫 | 国产无码啪啪视 | 国产精品日日摸夜夜添夜夜添1 | 国产精品无码a∨在线播放 国产精品无码aⅴ精品影院 | 国语自产偷拍精品视频 | 国产熟妇另类久久久久 | 国产成人高清综合在线 | 东京无码熟妇人妻av | 国产成人精欧美精品视频 | 国产三香港三韩国三级 | 精品人妻视频一区二区三区 | 91在线无码精品看片 | 精品无码免费在线播放 | 国产午夜精品理论片久久久 | 91精品国偷自产在线电影 | 91成人影院在线观看 | 国产日韩欧美另类精品色综合 | 国产一区二区三区免费大片天美 | 国产日韩精品99久久 | 国产白丝在线 | 国产种子在线看网站在线观看 | 精品高清不卡 | 国产麻豆视频 | 91人妻无码一区二区精品免费 | www.中文字幕一区二区 | 国产熟女一区二区三区十视频 | 国产午夜不卡av免费 | 国产一区二区精品久 | 国产成人夜色高潮福利影视95 | 国产尤物二区三区在线观看 | 精品国产一区二区三区蜜桃 | 91久久国产口精品久久久久 | 国产精品亚洲精品一区二区 | 国产成年女人免费视频播放a | 精品97人妻无码中文永久在线 | 91av视频在线观看 | 怀孕动漫精品国产一区二区三区 | 99久久久无码国产精品古装 | 国产成人综合亚洲av小说 | 国产成人综合欧美视频 | 成人国产一区二区精品 | 动漫av专区 | 国产大学生无码理论永久免费 | 国产成人午夜精华液 | 精品久久精品中文字幕无码 | 91极品视频 | 国产在线精品成人 | 91九色老熟女免国 | 国产午夜无码专区喷水 | 国产原创中文无码精品视频 | 动漫精品亚洲一区二区 | av片在线播放网址 | 国产麻豆成人传媒在线观看 | 国产麻豆精品一 | av免费网站在线观看 | 国语久久无码高清 | 国产欧美日韩制服丝袜三区 | 精品三级亚洲免费 | 国产成人8x视频网站 | 国产精品毛片完整版视频 | 国产麻豆精品国产三级国产av | 国产白丝喷水娇喘视 | 国产精品线在线精品 | 国产重口老太和两个小伙另类 | 激情刺激欧美一区二区三区 | 国产精品白丝jk喷水视频 | 国产精品国三级国产av视色 | 97色伦97色| 国产午夜福利在线观看视频 | 国产精品午夜理论片在线播放 | 囯产免费一区 | 国产精品丝袜自慰在线观看 | 99久久国产热这里只有精品 | 2025国产精品一区二区在线 | 国产激情对白一区 | 国产91对白叫床清晰在线播放 | av人无码不卡影片 | 精品爆乳一区二区三区无码aⅴ | 国产午夜精品一区二区三区不卡 | 精品国产高清一区二区三区 | 91麻豆国产在线 | 91九色熟女 | 国产a级毛片免费视频一区二区 | 99久久久久免费精品国产 | 国产精品青青 | 国产1卡二卡3卡四卡乱码视频 | 国产在线观看麻豆 | 99国产精品欲一区二区三区 | 丰满人妻熟妇乱又伦精品劲 | 2025久久天天躁狠狠躁夜夜 | 99国产欧美精品久久久蜜芽 | 国产成本人片免费a∨短片 国产成本人片免费av | 国产91国自产一区 | 国产麻豆一精品一av | 国产a级毛片免费视频一区二区 | 国产福利95精品一区二区三区 | 国产亚洲日韩欧美另类丝瓜app | 2025免费高清电影大全 | 国产自无码视频在线观看手机 | a级国产片免费 | 福利一区二区三区微拍视频 | 成人在线永久 | 国产精品无码久久久 | 国产免费高清国产在线视频 | 国产精品亚洲专区在线观看 | 国产品九九久久久国产精品 | 国产一区二区三区在线观看免费 | 国产三级精品三级国产 | 91精品人妻一区二区三区蜜臀 | 国产精品无码制服丝袜网站 | 国内精品乱码卡一卡2卡 | 国产亚洲第一伦理第一区 | 国产自愉自愉免费24区 | 国产熟女一级毛片高清 | 国产+精品+无码视频 | 精品毛片高清一区二区 | 精品国产热久久中文字幕 | 国产91精品一区二区亚洲 | 国产波霸爆乳一区二区 | 国产成年无码久久久久毛片 | 国产精品无码一区二区三区不卡 | 国产精品碰碰现在自在 | 精品国产免费久久一级 | 国产毛片毛多水多密月 | 国产精品一区欧美日韩制服 | 国产精品一区二区国产 | 国产成年码av片在线观看 | 国产福利免费视频 | 精品人妻中文字幕无码 | 国产精品一区在线观看第一页 | 18禁裸体动漫美女无遮挡网站 | 国产经典自拍视频在 | 国产成人黄色在线观看 | 91大神大战酒店翘臀美女 | 成人午夜有码一区二区 | 国精品人妻无码 | 激情亚洲精品中文字幕 | 国产精品成人免费视频 | 国产一区二区三区乱码在线 | 成人区人妻精品一区二区不卡麻豆 | 国内精品视频一区二区三区八戒 | 精品少妇人妻av无码专区不卡 | 91av成人日本不卡三区 | 国产无套码aⅴ在线观看在线播放 | 国产毛片18片毛一级特黄 | 国产成人亚洲精品无码av软件 | 国产不卡精品一区二区三区 | 国产精品免费热播 | 国产成人免费观看在线视频 | 国产一区在线主播中文 | 国产福利一区二区三区视频在线 | 国产成人无码a区在线观看视频 | 国产精品日日摸夜夜添夜夜添 | 99精品无码一区二区毛片免费 | 91精品福利麻豆专区 | av无码中文一区二区三区四区 | 国产aⅴ天堂无码一区二区三区 | 91人人 | 国产熟女真实乱精品 | 91精品国产在热久久下载 | 69国自产在线老师啪不卡 | 国产成人在线播放免费视频 | 3d无码纯肉动漫在线观看 | 国产av演绎护士 | h无码精品动漫在线观看导航 | 国产精品国产三级国产三级 | 2025国自产一点都不卡 | 国产毛片av一区二区三区 | 国产丝袜足交在线观看 | 东京热无码中文字幕电影 | 激情久久一区二区三区 | 国产人妖在线 | 国产成人久久精品一区二区 | 高清欧美三级自拍 | 1000部未满十八禁止观看 | 精品日本一区二区三区在线观 | 国产一区二区三区四区观看 | 国产一区二区无码视频 | 国产高清精品福利私拍国产 | 国产女学生破女初在线观看 | 91久久婷婷国产综合青草 | 国产精品偷窥熟女精品视频 | 国产在线观看乱码精品 | 18禁无遮挡羞羞污污污污免费 | 国产精品亚洲专区在线 | 国产精品美脚玉足脚交欧美 | 911精品国产91久久久久 | 成人夜色香网站在线观 | 东京一本一道一二三区 | 国产爆乳美女 | 国产成人麻豆精品午夜福利在线 | 精品三级一区二区 | 国产成人综合αv在线 | 精品国产一区二区三区香蕉p | 东京热精品| 91亚洲自偷手 | 高清不卡免费一区二区三区 | 国产成人精品午夜视频 | 成人亚洲国产精品无码久久一线 | 国产精品视频一区二区三区免费 | 97色小说天天射免费视频 | 国产高潮视频在线观看 | 国产中文字字幕乱码在线电影 | 国产成人自拍视频 | 国产在线精品二区 | 国产成人剧情av麻豆果冻 | 国产精品人妻免费视频 | 成人h网站在线 | 国产午夜精品一区二区三区不卡 | 国产精品一区成人精品五月 | 国产高清在线播放刘婷91 | 国产精品一区二区三区av | 精品国产免费看久久久 | 国产v一区二区三区日 | av日韩人妻黑人综合无码 | 国产91视频免费 | 国产成人精品免费视频大 | 国产女人高潮抽搐喷水视频 | 成人三级在线播放线观看 | 国产精品无码一区二区三四区 | 成人欧美一区二区三 | 国产一区二区无码精品久久 | 国产精品国三级国产aⅴ | 91高清国产| 91亚洲一| 潮喷好爽在线观 | 岛国岛国免费v片在线观看 岛国动作片免费免费全集观看 | av无码精品一区二区三区四区 | 国产午夜福利一区在线观看 | 国色精品va在线观看免费视频 | 丰满人妻一区二区三区视频 | 国产精品一区二区久久毛片 | 国产白浆喷水在线视频免费看 | 国产精品激情综合久久 | 99国产精品99久久久久 | 国产作爱视频免费 | 国产福利一区 | 91麻豆产精品久久久久久夏晴子 | 91午夜福利影视 | 成人无码区免费aⅴ片在线观看 | 国产在线一区二区91 | 国产按摩推油一区二区三区在线 | 国产精品日产欧美在线一区 | 国产巨作原创 | 国产成人免费高清 | 国产精品免费久久久久久久蜜桃 | 国产成年无码久久久久下载 | 国产交换配乱婬视频 | 国产中文欧美在线视频 | 91精品国内久久久久精品一本 | 2025亚洲爆乳无码专区 | 国产成人综合亚洲无码中字 | 国产成人精品高清在线观看93 | 2025国产在线观看无码 | 国产制服丝袜av不卡在线观看 | 国产午夜精品一区二区三区播放 | 国产午夜精品一区二区不卡 | 黑色丝袜老师自慰喷水浪潮免费 | 国产高清白丝一区二区 | 国产成人精品午夜日本亚洲 | 国产成人一区二区三区综合区 | 国产丝袜足交在线观看 | 国产超级乱婬av片 | 精品国产无码一区二区 | 国产一区二区三区无码免费 | 国产成人麻豆精品午夜福利在线 | 精品无码一区二区三区爱欲 | 国产精品高清一区二区不卡 | jk制服白丝 | 国产精品美女久久久久av爽 | 国产精品无码一区二区三区毛片 | 成人国产精品一级**片视频 | 2025国产午夜福利久久 | 高清精品一区二区 | 国产av无码国产av毛片 | 国产精品无码久久四虎 | 国产高清国产精品国产k | 国产熟女露脸大叫高潮 | 丰满白嫩大屁 | 寡妇高潮一级毛片免费看 | 东京热成人电影网 | 国产高清免费在线观看精品 | 精品婷婷色一区二区三区 | 成人精品一区二区三 | 国产一区二区视频在线观看 | 1024手机看片基地你懂的 | 91婷婷韩国麻豆一区二区 | 国产一在线观看视 | 国产精品福利免费观看 | 91制片厂制作传 | 国产成人a亚洲综合无码 | 3d肉蒲完整版下载 | 国产欧美精品久久一区 | 国产91网站在线 | 2025久久国自产拍 | 国产精品免费视频一区二区三 | 国产精品亚洲天堂 | 精品国产色欧洲激情 | 国产精品午夜无码av在线播放 | 91久久精品国产亚洲a∨麻豆 | 国产精品无码一区二区三区毛 | 2025国产精品香蕉在线观看 | 成人国内精品久久久久影院 | 91精品一区国产高清在线 | 国产a级国片免费播放 | 国产无套内射又大又猛又粗又爽 | 国产一区二区三区精品区在线 | 丰满肥臀大屁股熟妇激情 | 国产精品一区二区男人的 | 国产午夜理论线观看 | 国产古代三级在线播放 | 国产精品视频第一区二区 | 国产91精品一区在线观看 | 国产av一区二区三区最新精品 | 91精品云霸高清中文字幕 | 国产成人av| 爆乳熟妇一区二区三区 | 精品国产另类欧美精品 | 国产熟女一区二区三区五月婷 | 国产激情视频在线浏览 | 国产激情无码久久 | 2025亚洲国产精品无码 | 操操网站| 国产午夜精品一二区理论影院 | 国产一区二区三区在线观看免费 | 国产盗摄视频一区二区三区 | 国产熟女真实乱精品视频 | 国产成人户外露出视频在线观看 | 国产麻豆性爱视频 | 国产精品日韩电影制服丝袜 | 国产一精品一av一免费爽爽 | 国产精品亚洲国产在 | 国产午夜精品片一区二区三区 | 18禁裸乳无遮挡高清免费观看 | 国产高清视频一区二区在 | 国产av国产精品白丝jk制服 | 国产午夜男女爽爽爽爽爽视频 | 国产中文字幕一级片在线观看 | 国产盗摄女厕美女嘘嘘 | 国产精品高颜值 | 国产精品国产自 | 国产ww久久久久久久久久 | 岛国无码免费不卡av | 精品久久久久久无码人妻中文 | 国产成人激情一区二区视频 | 国产毛片高清无打码在线 | 国产精品一区在线 | 国产综合内射日韩久 | 国产成人av乱码在线观看 | 国产黄色在线播放 | 国产在线精品一区二区在线看 | 国产精品无码无卡毛片不卡视 | 国产成本人片免费av | 国产午夜激无码色本v毛片 国产午夜精华2025在线 | 高潮白浆潮喷正在播放 | 波多野结衣中文字幕全集 | 97人妻天天摸天天爽天天 | 国产精品国产三级国产aⅴ 国产精品国产三级国产aⅴ9色 | 91九色视频在线观看 | 国产精彩视频一区二区三区 | 国产成人综合亚洲亚洲国产第一页 | 成在线人视频免费视频 | 国产三级农村妇女在线 | 潮喷大喷水系列无码 | 加勒比人妻av无码不卡 | 精品久久a人妻 | 国产精品热久久毛片 | 99久久国产综合精品swag | 精品国产一区二区三区不卡 | 国产成人无码a区在线 | 国自产拍视频在线网站 | 国产在线观看国自产偷精品产拍 | 91麻豆产精品久久久 | 国产一本通av在线正在播放 | 国产av无码专区亚汌a√ | 国产高清综合中文 | 国产尤物高清在线观看 | 国产精品成人小电影在线观看 | av无码中文字幕不卡一二三区 | 国产粗语刺激 | 精品视频在线观看一区二区三区 | 国产亚洲欧美日韩在线三区 | 精品午夜福利国产一区二区在线观看 | 国产成人麻豆精品午夜福利在 | 国产在线一区二区三区视频 | 国产白袜 | 91免费无| 国产精品美女久久久久久久 | 国产一区二区三区视频xxx | 国产91精品露脸国语对白 | 国产成年无码a影片在线观看 | 18禁无遮挡无码啪啪网站 | 东京热一区二区免费高清av | 国产在线视频国产永久视频 | 国产av无码无遮挡毛片 | 精品人妻无码一区二区三区换脸 | 爆乳上司julia中文字幕 | 国产av秘无码一区二区三区 | 国产精品午夜无码av在线播放 | 国产成人午夜无码电影在线观看 | 91精品国产综合久久青草 | 国产欧美高清精品一区2 | 国产精品熟女四五十路一区二区 | 99久久久无码国产精品不卡 | 国产高清午夜人成在线观看 | 91在线精品 | 国产精品麻豆99久久久久久 | 成人色综合综合网站 | 91丝袜诱惑一区 | 国产熟女一区二区三区十视频 | 1024国产精品视频一区 | 国产熟女精品一区二区 | 精品丝袜国产在线播放 | 国产女同一区二区在线 | 国产精品一品二区三区四区 | av每日更新在线观看 | 91国内外精品自在线播放 | 国产高清无码在线视频播放 | 国产护士囗交吞精视频 | 韩国无码一区二区三区在线观看 | 高潮又爽又黄又无遮挡动态图 | 国精产品自线在拍在线精品 | 国产精品成人无码av毛片 | 国产999精彩视频 | 国产精品国产三级国产无码 | 国产午夜福利在线永久视频 | 国产av无码专区亚洲版综合 | 国产精品欧美一区二区 | 91在线国偷自产一区国产永久 | 国产女同互慰高潮流水视频 | 97精品国产自在现线拍 | 91丝袜兔女郎羞羞软件 | 国产高清精品在线91 | 91精品国产高清久久久电影 | 国产成年无码aⅴ片在线观看 | 国产高清精品一区二区 | av日韩中文地址 | 国产精品一区二区三区四区 | 国产在线精品福利一区二区三区 | 国产按摩推油一区二区三区在线 | 加勒比精品综合在线 | 国产精品v在线观看无码 | 国产精品午夜国产小视频 | 国产亚洲综合区成人国产系列 | 爆乳熟女av一区 | av在线免费观看网站 | 国产亚洲视频在线观看 | 国产成人8x人网站视频下载 | 国产精品毛片一区二区三区 | 国产成a人亚洲精v品无码 | 精品国产亚洲av高清在线观看 | 国产夫妻内射一级一片 | 福利国产微拍广场一区视频在 | 国产人妖专区 | 99国产精品国产精品九九 | 国产91丝袜在线播放网站 | 国产成人精品高清免费 | 国产成人综合亚洲色 | 国产精品视频一区二区三区四 | 91福利国产在线观看网站 | 国产剧情高潮调教颜射勾引 | 国产av天堂亚洲国产av麻豆 | 国产真实乱对白精彩久久老熟妇女 | 精品国产伦一区二区三区在线 | 国产a级精精彩大片免费看 国产a级精品一级毛片 | 国产精品三p一区二区视频 国产精品三级 | 成人在线免费激情 | av之家免费黄片 | 国产午夜手机精彩视频 | a极毛片一区二区三区免费看 | av无码成人精品区在线观看 | 国产欧美日韩一区二区三区四区 | 国产亚洲欧美一区二区在线观看 | 国产一区二区三区乱码在线观看 | 国产精品日韩在线观看 | 91精品亚洲欧美一区二区综合 | 国产综合成人观看在线 | 国产亚洲日韩av在线播放 | 国产精品国产对白熟妇 | 国产成人美女福利在线观看 | av片在线观看免费 | 国产精品人妻无码一区牛牛影视 | 99久久无码 | 国产午夜无码精品免费看粉 | 国产麻豆va在线观看 | 国产免费怕怕免费视频观看 | 国产成人亚洲欧美日韩精品 | 激情都市亚洲一区二区 | 国产亚洲欧美日韩综合综合二区 | 国产亚洲精品久久久美女 | 国自产拍线色青 | 国产精品欧美日韩另类中文 | 国产精品成人三级 | 国产精品三级一区二区三区 | 成人黄色一级电影在线免费观看 | 18禁肉肉无遮挡无码网站 | a级国产乱理论片在线观看av | 2025韩国午夜福利片在线观看 | 国产成人免费无码视频在线观 | 国产午夜无码片免费 | 成人一区二区三区在线播放 | 国产艳妇av在线出轨 | 国产aⅴ一二三区无码视频 国产aⅴ一区 | 国产精品国产三级国产av剧情 | 国产自拍精品在线观看 | 国产一区二区理论在线观看 | 东京热高清无码系列 | 国人国产免费av影院 | 精品无码一级午夜一区二区 | 国产午夜无码 | 国产精品人妻无码一区牛牛影视 | 99久久综合狠狠综合久久浪潮 | 国产午夜高清无 | 国产美女视频免费观看的网站 | 91在线电影 | 国产精品大战 | 国产成人精品福利网站人 | 精品人妻中文字幕 | av中文字幕剧情不卡 | 精品人妻系列无码区久久 | 国产女主播精品视频一区 | 18禁高清无遮挡一 | 国产不卡手机在线视频 | 18禁午夜福利a级污黄刺激 | av一本久道久久波多野结衣 | 国产麻豆亚洲精品 | 国产精品盗摄一区二区在线 | 国产三级精品三级在线专区 | 国产高清av在线播放无弹窗 | 国产真人无码作爱免 | 精品国产99久久 | 国产成人精品无码免费播放 | 精品无码欧美黑人又粗又 | 国产一区二区内射最近更新 | 国模无码一区二 | 精品日本亚洲一区二区三区 | 国产精品视频二区不卡 | 国产无码黄色网站在线观看 | 91精品欧美一区二区综合在线 | 国产熟女一区二区精品免费 | 国产成人综合亚洲欧洲色就色 | 国产麻豆精品成人免费视频 | 18禁成年无码免费 | 福利一区在线视频 |