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

半岛外围网上直营

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

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

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

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

相關鏈接:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

處理導航的生命周期

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

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

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

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

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

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

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

導航與參數

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

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

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

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

由于命名約定,我們不需要做任何特別的操作:新頁面和新ViewModel已經連接?,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: 關于移動開發,這些產品你可以關注>>
關于移動開發的最新資訊和產品推薦,請<>!

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

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


為你推薦

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


添加微信 立即咨詢

電話咨詢

客服熱線
023-68661681

TOP
利記足球官網(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) 真人boyu·博魚滾球網(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) 最大網上PM娛樂城盤口(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) 正規雷火競技官方買球(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) 雷火競技權威十大網(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) boyu·博魚信譽足球官網(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) 權威188BET足球網(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) 正規188BET足球大全(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) 2025亚洲天堂无码视屏手机版 | 国产福利姬精品福利 | 91久久久久精品无嫩草影院 | 3p国产对白刺激在线视频 | 精品国产蜜桃乱码久久久久 | 波多野结衣人妻在线一区二区 | 国产一区在线观看无码av | 国产精品对白交换 | 国产成人免费高清激情明星 | 国产成人精品电影在线观看 | 91成人午夜性a| av午夜片在线观看 | 国产露脸无码a区久久蘑菇 国产乱aⅴ一区二区三区 | 成年性生交大片免费看 | 国产gv猛男gv无码男同网站 | 国偷自产一区 | 91精品极| 91大神最新国自产拍在线播放 | 动漫av永久无码精品每日更新 | 2025国产主播精品 | 2025年最新高清热播电影 | 国产美女喷水白浆 | 国产aⅴ无码专区亚洲av麻豆 | 国产精品欧美久久久久无广告 | 国产高清在线精品一区二区三区 | 国产精品韩国一区二区三区 | 国产日韩一区二区三区在线观看 | 国产一区二区在 | 国产色婷婷精品免费视频 | 91午夜精品亚洲一区二区三区 | 国产色婷婷免费视频 | av一区二区三区不卡在 | 狠狠色婷婷久久一区二区三区 | 国产不卡精品一区二区三区 | 成人午夜无码 | 精品国产一区国产二区国产三区 | 3d动漫精品啪啪一区二区中文 | 精品一区二区二区四区五区 | av免费观看 | 国产成人午夜高潮毛片 | 国产日韩一区二区三区免费高清 | 国语精品一区二区三区 | 丰满的岳乱妇久久久 | 国产精品欧美福利久久 | 精品国产品国语原创 | 国产欧美日韩综 | 国产精品狼人 | www夜片内射视频日韩精品成人 | 国产成人综合激情 | 国产成人a亚 | 国产高清一区二区三区四区五区 | 东京热av人妻无码专区 | 国产午夜成人免费看片 | 国产成人精品免费视频 | 国产精品一区二区六 | 91视频官网入口 | 国产免费高清视频在线观 | 国产超清综合在线视频 | 18国产精品白浆在线观看免费 | 国产1卡2卡三卡四卡久久网站 | 成人无码区免费aⅴ片黄瓜 成人无码区免费aⅴ片在线观看 | 97人妻无码免费专区 | 99久久精品亚洲国产 | 2025中文字幕在线无码视频 | 国产日韩欧美一区二区久久精品 | 国产亚洲成aⅴ人片在线观看蜜桃 | 国产成人免费视频在线观看 | 高潮一区二区三区 | 韩国午夜无码片在线观看 | 国产美女精品人人做人人爽 | 国产精品成人无码a片免费网址 | 国产精品毛片久久久久久 | 国产a免费观看不卡 | 国产av熟女一 | 国产一级片内射在线视频播放 | 国产一区二区三区亚洲欧美 | 国产欧洲黄色一级片视频 | 国产午夜福利电影在线观看2 | 国产三级主播在线观看 | 国产精品毛片大码女人 | 国产一区二区高清在线播放 | 国产精品你懂的在线资源观看 | 国产精品免费久久久久久久久久 | 国产精品白浆无码流出 | 国产成人久久精品二三区麻豆 | 国产午夜鲁丝片av无码免费 | av无码一区二区三区波多野 | 精品国产精品国产自在久国产 | 国产成人理论 | 高清无码一区二区在线观看吞精 | 国产成人mv毛毛a片 国产成人mv在 | 国产日韩av无码专区aaa | 国产不卡视频在线播放 | 69式真人无码精品视频免费 | 国产人妻精品 | 国产精品毛片无码一区二区蜜桃 | 国产一区二区三区不卡在线观看 | 成人日韩无码动漫秘一区二区 | 国产欧美日韩在线一区二区 | 精品秘无码一区二区三区 | 91精品最新国内在线播放 | 国产一区鲁鲁在线视频免费播放 | 国产精品精品自在线看 | 国产高清美女一级毛片录像 | 国产在线永久视频 | 精品国产aⅴ一区二区三区4区 | 国产欧美日韩综合精品一区二区三 | 国产麻豆天美果冻无码视频 | 国产成人免费av片在线观看 | 国产免a在线观看 | 国产精品一区看片 | 国产精品好爽好紧好 | 国产色精品vr一区区三区 | 99久久精品国产一区二区麻豆 | 国产精品一区在线播放 | 国产一区亚洲一区在线观看 | 国产亚洲精品看片在线观看 | 国产精品大片在线 | 国产精品卡 | 国产综合精品一区 | 国产成a人亚洲精ⅴ品无码性色 | 苍井空一区二区三区在线观看 | 成人综合色在线 | 国产精品国产三级国产av | 国产三级aⅴ在线播放 | 国产亚洲成aⅴ人片在线观看嫩草 | 国产福利95精品一区二区三区 | 国产精品激情综合久久 | 国产午夜免费看黄片 | 成人免费无码大片a毛片抽 成人免费无码大片a毛片抽搐 | 国产在线观看午夜天堂 | 国产在线观看超清无码视频一区二区 | 囯产精品一区二区免费在线观看 | 国产午夜无码精品免费看性色 | 爆乳美女脱内衣18禁裸露网站 | 国产成人精品999在线观看 | 国产成人精品免费视频大全 | 国产绿帽在线视频看 | 福利一区二区三区视频播放 | 国产91精品免费在线观看 | 国产成人福利一区二区三区 | 国产韩国欧美日本在线 | 精品少妇一区二区三区视频 | 成人午夜福利免费专区无码 | 91在线无码精品国产三年 | 动漫精品专区一区二区三区不 | 国产福利精品一区二区 | 91麻豆精品国产自产果冻传媒 | 国产成人无码午夜视频在线观看 | 国产精品四虎在线观看免费 | 国产精品毛片久久久久久久 | 精品福利一区二区视频 | 国产av一区二区三区四区五 | 国产成人涩涩涩视频在线观看免费 | 国产爆乳无码视频在线观看3 | 高清无码在国产极 | 国产成人无码a区视频在线观看 | 国产精品天干天天 | 高清av一区二区三区在线观看 | 91精品国产福利在线观看 | 国产女同一区二区在线 | 国产亚洲欧洲人人网在线观看 | 另类欧美亚洲曰本 | 国产成人a视频高清视频在线 | 东京热高清中文字幕 | 91视频网站如何满足用户需求 | 2025精品1区2区3区芒果 | 国产精品成人观看视频网站 | 国产午夜精品一区二区 | 国产爆乳成av人在线播放 | 91在线最新精品国产 | 精品国产一区二区三区性色a∨ | 精品国产一区二区三区久久久蜜臀 | 极品女神的精彩世界 | 国产激情无码毛片久久 | 国产产无码乱码精品久久鸭 | 99久久精品国产一区二区免费 | 国产一区二区在线观看无码 | 91高清国产经典在线观看 | 国产成人国产在线观看入口 | 国产精品初高中精品久久 | 国产高清国产精品国产k | 国产精品久av福利在线观看 | 国产麻豆综合视频在线观看 | 国产精品系列在线观看 | 国产疯狂女同互磨高潮在线看 | 国产精品成人无码久久久 | 国精品一区二区av无码中文字幕 | 国产av乱码一区二区三区 | a级毛片无码兔费真人久久 a级毛片无码兔费真人久久91 | 国产国产成人高清视频 | 国产成a人亚洲精v | 国产自国产自愉自愉 | 91大神在线精品播放 | 99久久国产自偷自自偷蜜月 | 国产日韩欧美另类 | 国产成人av性色在线影院 | 91精品人妻一区二区三区浪潮 | 精品深夜av无码一区二区 | 动漫在线一区不卡精品 | 国产白浆精品 | 国产午夜亚洲精品一级 | 国产成人无码午夜视频在线观看 | 国产野战无套av毛片 | 国产成人亚洲精品无码vr | 国产精品夜夜春夜夜爽久久小说 | 国产区精品一区二区不卡中文 | 国产一级毛片特级毛国产 | 国产成人啪精品视频免费软件 | 国产精品成人va在线播放 | 国产亚洲视频网站 | 国产成人综合亚洲天堂 | 国产一区二区三区不卡在线观看 | 国产亚洲成a人片在线观看 国产亚洲成v人片在线观黄桃 | 69精品偷拍在线中文字幕 | 国产成人无码一区二区在线播放 | 国产区精品尤物柚木在线 | a级毛片免费观看在线播放 a级毛片免费看 | 岛国av无码免费无禁网站麦芽 | 国内精品一区二区三区 | 国产一区二区三区精品诱惑网站 | 91精品成人免 | 国产精品女同一区二区 | 国产精品高清全国免费观看 | 国产亚洲欧美在线专区 | 国产麻豆精品福利在线观看 | 国产成人av丝袜在线播放 | 国产人妻一区二区无码 | 国产av乱码一区二区三区 | 国产一区自拍视频 | av一本久道久久综合久久鬼色 | 国产亚洲色婷婷久久99精品91 | 国精产品一品二品国 | 精品少妇ay一区二区三区 | 国产91专区| 丰满人妻一区二区三区视频 | 国产一区内射最近更新 | 国产亚洲欧美在线观看三区 | 国产专辑免费在线不卡 | 成人国产日本亚洲精品 | 国产精品成人观看视频网站 | 国内精品乱码卡一卡2卡三卡 | 国产偷伦视频中文精品免费 | 国产福利91精品 | 不卡无码精品在线观看 | av无码专区亚洲avl在线观看 | 91久久久久久久国产 | 91精品国产一区自在线拍 | 成人午夜毛片一区二区 | 国产成人精品视频一区二区不卡 | 国产成在线观看免 | 国偷自产av一区二区三区不卡 | 2025久久国产精品毛片 | 国产盗摄精品一区二 | 国产精品无码影视久久久久久久 | 国产最爽的乱婬视频国语对白 | av免费午夜福利不卡片在线观看 | 精品一区二区三区盗摄 | 国产美女流白浆 | 国产一区二区三区av无码 | 国产av秘无码一区二区三区 | 国产成人av一区二区三区在线 | 国产三上悠亚日韩在线 | 3d成年av动漫网站 | 国产成本人片无码免费 | 高清欧美日韩一区二区三区在线 | 国产91久久久久久久免费 | 91桃色无码国产在线观看二区 | 国产精品一区在线播放 | 国产91精品对白露脸全集观看 | 国产免费无码av片在线观看不 | 国产成人精品免费视频 | 国产精品视频色拍拍 | 国产精品毛片无遮挡 | 国产黄色带三级在线观看 | 国产三级电影院电影 | 激情啪啪精品一 | 高清无码黄色视频在线观看 | 国产人妖视频一区二区女 | 国产刘玥在线视频观看 | 国产色欲av一区二区三区麻豆 | 国产91自拍视频 | 国产毛片a级久久久不卡精品 | 国产成a人亚洲精v品在 | 91蜜桃国产成人精品区在线观看 | 寡妇高潮一级毛片 | 丰满的岳乱妇久久久 | 91在线无码精品秘入口九色下 | 二区三区四川人 | 国产精品无码一区二区久久 | 国产成人麻豆精品午夜福利在 | 国产精品小视频91 | 国产亚洲欧美另类在线第1页 | 国产精品视频无码一区二区免 | av无码免费永久在线观看 | 成人精品国产区在线观看 | 国产精品视频色综合网综合色 | 99精品免视看 | 国产成人av三级在线观看按摩 | 国产女同疯狂作爱系列 | 动漫精品专区一区二区三区不 | 加勒比东京热av | 国产成人永久免费高清 | 2025最新手机在线 | 国产精品亚洲玖玖玖在线观看 | 国产麻豆精品乱码一区 | 国产欧美日韩在线视综合网频 | 国内精品视这里只有精品 | 国产野战正规军全 | 丰满人妻精品 | 成人国产片免费在线观看 | 高清无码毛片国产 | 极品人妻无码在线 | 精品国产高清一区二区广区 | 国产美女嘘嘘嘘嘘嘘视频 | 1区2区3区国产av天堂 | 国产精品无码免费专区午夜 | 国产日韩午夜毛片电影完整版 | 国产一区无码 | 国产素人一区二区久久 | 国产综合精品久久亚洲 | 国产aa片日韩一级观看 | 国产麻豆精品传媒av | 国产成人午夜91精品麻豆剧场 | 国产美女爽到尿喷出来视频 | 国产成人一区二区三区影院免 | 91高清免费国产自产拍不卡 | 韩国久久九九精品 | 91精品国产现在观看 | 国产成人无码aa精 | 97人人模人人爽人人少妇 | 91久久精品无码一区二区大 | 国精产品自线在拍在线精品 | 国产亚洲第一精品综合av | 国产熟女一区二区五月婷 | 成人毛片无码一区二区三区 | 国产成人午夜福利影片 | 高清免费视频一区二区三区 | 国产一级毛片一级毛片视频 | 国产国语精品对白无码视频 | 国产激情无码视频在线播放性色 | 18禁黄污无遮挡无 | 国内免费视频一区二区三区 | 爆乳无码av一区二区三区 | 精品国产尤物一区二区三区 | 爆乳美女脱内衣18禁裸露网站 | 国产日韩一区二区不卡视频 | 国产在线第一浮力影院 | 精品少妇一区二区三区视频 | 国产av高清一 | 国产极品美女高潮无套在线观看 | 99久久精品国产波多野结衣 | 国产极品粉嫩福利姬萌白酱 | 国产精品熟女人妻久久 | 国产成人一区av | 国产一区二区在线观看动漫 | 国产麻豆一精品一av一免费 | 国产99久久久欧美黑人 | 国产欧美va天堂在线观看视频 | 国产成人无码精品久久久露脸 | 国产精品国内免费一区二区三区 | 91精品一区二区三区在线观看 | 高清无码在线一区二区 | 国产麻豆成av人片在线观看 | 国产成人精品一区二区免费 | 国产高清在线精品一本 | 国产精品日韩电影制服丝袜 | 加勒比中文字幕无码 | 国产偷倩视频 | 91精品丝袜国产在线一区 | 国产91无套剧情在线播放 | 国产成人久久精品二三区麻豆 | 91成人精品爽啪在线观看 | 国产野外无码理论片 | 国产精品兄妹在线观看麻豆 | 国产日韩a视频在线播放视频色欲 | 91精品久久| 国产精品国内自产拍在线播放 | 99精品全国免费观看视频 | 韩国卡通动漫一区二区精品 | av中国美女在线观看 | 国产极品白嫩精品无码视频 | 国产高潮流白浆喷水免费网站 | 97人妻一区免费精品 | 国产精品无码亚洲 | 精品国产一区二区三区av片 | 国99久9在线 | 动漫日韩无码一区 | 国产精品成人观看视频国产 | 国产精品成人精品天天看视频 | 囯产极品美女高潮无套久久久 | 国产精品无码影视久久久久久久 | 国产精品亚洲无码第一页 | 成人精品一区二区三区免费视频 | h无码精品动漫在线观看免费 | 潮喷失禁 | 91久久精品无码一区二区免费 | 国产精品毛片一区二区三区在线 | 二区在线观看免费 | 成人午夜福 | 91在线视频 | 国产超碰āv人人做人人爽 国产超碰女人任你爽 | 国产欧美日韩在线视频重口味 | 精品无码专区在线视频 | 国产精品日韩欧美在线第一页 | 国产成人精品亚洲精品 | 国产精品无码久久久久 | 91精品导航在线观看 | av一区二区人妻无码 | 国产1精品国产亚洲区久久 国产1卡2卡三卡四卡久久网站 | 成人国产精品秘久久久 | 国产一区二区三区精品网站 | 91欧美激情欧美性爱综合 | 国产成本人片无码免费 | 国产蜜桃扣扣传媒av性色 | 高清无码在线观看流畅不卡 | 国产91精品露脸国语对白 | 国产成人国拍亚洲精品 | 精品福利一区二区三区在线观 | 国产一区鲁鲁在线视频免费播放 | 国产av无码不卡 | 99久久无码一区人妻久久 | 精品国产乱子伦一区二区三区r | 韩国男男腐啪gv肉视频 | 国产成人久久精品二三区麻豆 | 国产av无码专区亚洲av琪琪 | 国产精品原创在线网址 | 91免费网站在线看入口黄 | 国产激情一区二区三区app | a级毛片免费看久久 | 成人午夜激情福利动态 | 国产无码精品在线 | 爆乳美乳无码敏感乳在线播放 | 岛国无码在线观看精品 | 国产av大毛片一区二区 | 国产成人精品亚洲午 | 国产野外强奷系列在线播放 | 国产精品多p对白交 | 国内自拍亚洲精选在线观看 | 2025国产视频| 国产精品日韩欧美一区二区 | 国产在线视精品在一区二区 | 国产欧美日韩丝袜精品一区 | 国产高潮呻吟久久 | 国产欧美二区三 | 国产大片免费观看网站 | 91夜色国产在线 | 9a1v精品少妇一区二区三区 | 二区视频在线观看 | 国产成人无码av片在线观看不卡 | 国产aⅴ视频免费观看国语 国产aⅴ视频视频在线 | 国产精品女人呻吟白浆在线观看 | 韩国国产精品一区二区三区 | 91亚洲精品国产自 | 国产在线精品国自产拍影院同性 | 国产日韩一区二区精品在线播放 | 国产午夜福利片在线播放 | 精品无码一区二区三区免费看 | 91精品国产综合久久四虎久久 | 国产精品在线就撸 | 国产亚洲3p无码一区二区三区 | 国产91专区一区二区 | 精品国产丝袜久久久久久无码 | 国产一区二在线观看 | 99久久久国产精 | 国产女人喷潮在线观看视频 | 国产激情一区二区三区在线观看 | 高潮毛片无遮挡高清视频播放 | 国产麻豆a片 | 国产小视频你懂的在线欧美 | 国产高清在线播放 | 国产成人久久精品麻豆二区 | 精品免费一区二区在线 | 国产在线观看免费视频软件 | 加勒比在线视频男人的天堂 | 国产欧美精品另类又又 | 国产高潮流白浆 | 国产午夜精品毛片不卡 | 国产av一区二区三区导航 | 国产高清吃奶成免费视频网站 | 丰满美女一级毛片不卡在线播 | 国产91精品白浆无码流出久久 | 成人女人看片免费视频放人 | 国产一区二区高清 | 1024国产精品免费观看 | 国产精品特级毛片一区二区 | 国自产在线精品 | 97人妻超级碰碰碰 | 国产精品成人在线 | 国产三级野外直播在线 | 国产精品无码一级毛片不卡 | 国产精品天码无卡在线观看 | 国内精品一区二区三区不卡 | 国产av无码片 | 国产欧美精品午夜在线播放 | 91蜜桃国产成人精 | 成人精品在线 | 99久久6动漫 | 福利视频综合一区二区三区四区 | 国产高清无码久久 | 精品午夜福利国产一区二区在线观看 | 国产精品无码av天天爽 | 白浆喷水了 | 91亚洲欧美激情 | 国精产品一品二品国 | 精品亚洲一区二区三区在 | 国产三级在线观看视频不卡 | 国产亚洲第一午夜福利合集 | 国产成人av无码片在线观看 | 国产孕妇直播在线观看 | 69精产国品| av喷水高潮喷水在线观看c | 国产成人精品久久久久欧美 | 国产一区二区三区免费看 | 国产色妞妞在线视频免费播放 | 国产精品一区二区三区视频 | 成人无码区免费a片在线软件 | 国产精品人妻无码一 | 国产成人av在线婷婷不卡 | 国产巨臀系列在线观看 | 加勒比东京热久久久 | 99国产成人 | 国产成人综合亚洲 | 国产女王强制射精在线 | 国产精品一区二区熟女不卡 | 国产欧美日韩综合精品久久一区 | 成人精品天堂一区二区三区 | 国产精品精品自在线拍 | 18禁美女黄网站色大片免费 | 精品国产高清在线观看国产 | 国产v亚洲v天堂a | 国产一级毛片大片大全 | 国语自产偷拍精品视频偷拍 | 精品国产96亚洲一区 | 91福利国产在线观看香蕉 | 国产av女人久久精品 | 精品一区二区高清免费观看 | 国产美女深夜福利在线一 | 国产三级直播在线播放直播 | 丰满少妇五月天电视剧在线播放 | 97人妻免费视频中文 | 成a人影片免费观看日本 | 国产精品精品系列在线观看 | 精品人妻无码区在线视频 | 国产自无码视频在线观看手机 | 91热久久免费频精品黑人99 | 岛国av无码免费无禁网站麦芽 | 国产精品国产精品一区二区 | 丰满肥女巨肥bw | 国产猛男猛女超爽免费视 | 国产国拍亚洲精品永久污 | 国产日韩久久久一区二区三区 | 东京一本大道无码 | 国产成人综合在线视频 | 国产91精品久久久久999 | 黄色a片三级三级三级免费在 | 妓女妓女影院妓女视频妓女影库 | 爆乳无码专区 | 国产精品视频第一区二区三区 | 国产精品色婷婷亚洲综合看片 | 精品久久二区二区 | 国产精品无码亚洲精品2025 | 国产日韩无码影院一区二区三区 | av三级片在线 | 国产精品福利在线观 | 国产精品一国产精品免费 | 成年午夜免费aⅴ在线观看 成年午夜无码av片在线观看 | 国产精品三级av在线 | 国产精品国产三级国产在线主播 | 精品久久久久久久一区二区伦 | 高潮一区二区三区 | 国产深夜福利在线免费观看 | 高清国产一区二区三区 | 精品国产一区二区三区不卡在 | 国产精品麻豆入口 | 国产精品午夜一级毛片 | 国产无码黄色网站在线观看 | 丰满人妻一区二区三区无码av | 国产人妻熟女在线观看高清完整 | 国产91熟女一区二区三区 | 国产精品一区二区三区久久久久 | 国产精品秘入口18禁麻豆免会员 | 国产丝袜一区二区在线播放 | 2025亚洲卡一卡二新区入口 | 国产v亚洲v天堂a无码久久蜜桃 | 极品粉嫩虎白女毛片 | 成人在线免费观看大全 | 成人综合亚洲日本一区二区 | 白丝爆动漫羞羞动漫网站 | 国产精品一区二区三区人妖 | 91精品国产色综合久久久蜜臀 | 国产精品无码播放 | a级毛片免费观看片 | 国产成人精品高清国产三级 | 国产成人精品本亚洲 | 国产av无码专区亚洲aⅴ | 国产精品va在线观看丝瓜影院 | 成人免费播放视频 | 国产av影片麻豆精品传媒 | 国产精品日韩激情无码 | 国产精品无码久久久久成人影院 | 97人妻在线视频观看 | 国内偷自拍对白视频 | av在线亚洲中文 | 成人dvd碟片 | 国产成人福利网站 | 国产精品无码av片在线观看播放 | 国产在线无码免费播放视频 | 国产精品一国产精品最新章节 | 东京热一区二区三区 | 成人a级毛片免费观看av一区 | 国产精品成人扳**a毛片 | 国产91最新欧美在线观看 | 丰满大屁股在线播放bbw | 国产超碰人人爽人人做人人添 | 精品无人区无码乱码大片国产 | 69国产精品成人无码免费视 | 精品国产片自在线拍免费看 | 9i精品福利一区二区 | 高清无码免费黄色大全 | 国产午夜精品福利 | 韩国精品一区二区三区久久 | 国产精品一区在线麻豆 | 国产系列在线频高清在线观看 | 国产成人精品一区二区三区免费看 | av天堂午夜精品一区二区三区 | 国产午夜福利大尺度在线观看 | 国产无码综合 | 91av自拍 | 国产精品日韩欧美 | 国产av巨作情欲放纵无码 | 国产成人av无码 | 国产成人5x人网站视频 | 2025国产精品国产精华 | 91久久嫩草影院 | 91免费无 | 国产人妖一区二区动漫黄片 | 国产精品美女av在线 | 精品日本一区二区三区在线观看 | 国产欧美精品一区二区三 | 国产精品无码一二区免费 | 国产尤物无码一区二区 | 国产精品无码一区二区三区免费 | 国产欧美日韩亚洲αv | 国产在线视频一区二区 | 91丝袜在线 | 国产不卡高清视频在线观看 | 国产高清视亚洲一区二区 | 911天堂国产在线观看 | 2025亚洲国产成a在线 | h无码真人在线观看 | 国产精品成人av三级在线 | 国产精品高潮露脸在线观看 | 东京热一区二区沙河无码网站 | 国产毛片精品高清一区二区 | 岛国无码免费不卡av | 国产v亚洲v天堂无 | 成人免费xxx在线观看 | 国产精品无码一区二区三区不 | 国产成人精品久久亚洲高清 | 国产高清成免费视频 | av一区二区在线观 | 2025国产乱人伦在线播放 | 国产中文字幕在线久 | 国产av激情久久无码天堂 | 国产精品美女久久久久久吹潮 | 国产91av在 | aⅴ人在线观看 | 国产偷窥在线 | 国产成人精品美女在线 | 国产精品亚洲片在线观看不卡 | 国产成人精品久久亚洲高清不卡 | 国产夫妻内射一级一片 | 91精品一区是什么 | 国产一区二区三区精品在线观看 | 成人毛片视频在线观看 | 成人国产精品一级**片视频 | 国产精品一级毛片在线不卡 | 国产精品丝袜无码不卡一区 | 丰满人妻熟妇乱又伦精品视 | 国产按头吞精在线视频 | 国产盗摄对白在线观看 | 国产在线一区二区观看 | heyzo无码综合国产精品 | av无码天堂一区二区三区 | 国产成人无码免费视频97动漫 | 国产主播一区二区 | 福利国产小视频 | 国产激情av一区二区 | av天堂电影网 | a级无码电影在线观看 | 国产精品亚洲欧美云霸高清 | 国产一区二区三区亚洲av | 高清亚洲精品一区二区三区 | 国产尤物aⅴ在线观 | 91美剧网 | 91日韩高清在线观看播放 | 国产一区二区三区欧美精品 | 国产a级毛片色咪味 | 国产成人精品久久 | 国产区香蕉精品系列在线观看不 | 精品国内一区二区三区在线 | 国产一区二区av免费 | 国产成人精品无码区电影 | 国产99re在线观看69热 | 国内一国产农村妇女一级毛片 | 精品人妻av中文字幕乱 | 国产肥熟女视频一区二区三区 | 国产成人精品电影在线观看18 | 国产无套露脸大学生视频 | 国产综合日本影视 | 国产高清国内精品福利99久久 | 成人免费一区二区三区视频 | 国产美女流出白浆在线观看 | 加勒比久久综合 | 国产黑色丝袜视频在线观 | 国产精品无码午夜福利 | 国产无码黄色视 | 国产成久久综合片 | 国产极品白嫩精品无码视频 | 国产无码一区二区三区动态 | 91嫩草国产线观看免费永久 | 国产精品九九在线播放 | 国产无套粉嫩白浆 | 国产精品一区二 | av在线播放 | 囯产精品一区二区三区乱码 | 爆乳少妇在办公室在线观看 | 国产裸体裸拍在线观看 | 91久久国产综合精品 | 99久久精品免费观看国产一区 | 国产中文字幕永久在线观看 | 国产aⅴ精品一区二区果冻 国产aⅴ精品一区二区久久 | 国产av无码专区亚洲八aⅴ | 爆乳一区二区无码 | 国产成人无码不卡精品久久久 | 国产亚洲欧美在线观看三区 | 东京一区二区三区高清视频 | 成a人无码午夜电影 | 成人黄免色a | 国产精品观看一区二区三区 | 国产美女精品在线 | 国产99对白在线播放 | 国语自产视频在线不卡 | 精品国产仑片一区二区三区 | av黄色网址在线观看 | 高清无码不卡视频 | 91精品隔壁老王在线观看 | 国产精品女人呻吟在线观看 | 国产午夜人做人免费 | 丰满多毛的大隂户视频 | 国产成人影院在线观看 | 国产在线第一区二 | 国产黑色丝袜在线视频 | 成人一区二区免费中文字幕视频 | 国产午夜精品久久久久婷看片 | 国产精品福利在线观看入口 | 国产91精品久久久久久 | 加勒比中文字幕无码久久 | 国产一区二区三区四区五区视频 | 国产精品午夜一区二区 | 国产av国片精品有毛 | 东京热无码人妻一区二区av | 国产高清在线精品一区 | 国产囗交口爆吞精在线视频 | 91视频免费观看 | 国产美女黄性色 | 国产精品自拍色网视频 | 91精品人妻一区二区蜜桃 | 不卡国产福利在线观看 | 国产在线自在拍91精品黑人 | 国产精品二区无 | 国产人人爽人人爱 | 国产熟睡乱子伦午夜视频麻豆 | 国产精品日韩欧美一区二区 | www夜片内射视频在观看视频 | 精品人妻一区二区三区夜夜嗨 | 加勒比无码 | 国产午夜片在 | 97人人澡人人爽 | 国产三级adc全集在线观看 | 国产成人久久久精品一区二 | 国产自在现偷国产精品国产日韩 | 国产成人精品怡红院在线观看 | 精品无码免费视频 | 国产成人乱码一二三区18 | 国产女人爽的流水毛片 | 国产成人综合亚洲天堂 | 国偷自产av一区二区三区吞精 | 国产免费伦精品一区二区三区 | 精品视频手机在线观看免费 | 国产成人精品免费久久久久 | 精品三级网站 | 国产极品高颜值美女在线 | 国产精品无码中出在线播出 | 国产日韩亚洲大尺度高清 | 国产成人精品a视频一区777 | 91精品人妻一区二区三区蜜臀 | www中国黄色一级片 wwxx在线观看免费 |