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

金喜正规买球

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

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

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

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

相關鏈接:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

處理導航的生命周期

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

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

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

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

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

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

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

導航與參數

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

結束語

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

本文翻譯自:

 

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

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

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


為你推薦

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


添加微信 立即咨詢

電話咨詢

客服熱線
023-68661681

TOP
国产第二页页在线播放 | 精品国内一区二区三区免费视频 | 国产日韩欧 | 永久免费影院 | 日本不卡中文字 | 欧美在线免费观看 | 欧美综合日韩 | 日本午夜福利 | 国产日产成人免费视频 | 亚洲精品一区二区三区四区五区 | 欧美国产在精品 | 国产亚洲一区激情小说 | 日韩精品三级一区二区 | 欧美日韩在线播放一区二区三区 | 一区二区三区四区在线观看视频 | 美女aⅴ高清电影在线观看 国产一区二区三区免费在线 | 妖精视频免费观看 | 性猛交╳xxx乱大交 欧美午夜理伦三级在线 | 青青国产精品一区二区 | 手机在线观看日韩电影大片 | 国产免费人成视频在线观看 | 日本野花视频在线观看 | 国产午夜场免费视频在线播放 | 女教师巨大乳孔中文字幕 | 东京干影院 | 99爱在线精品视频免费观看9 | 国产精品∧v在线观看 | 午夜福利国产一区二区三区 | 欧美日本在线播放 | 国产综合一区二区三区 | 一区二区在线免费观看 | 国产a国产片国产 | 微拍福利88 | 亚洲欧洲精品国产区 | 日韩精品中文字幕视频在 | 高清免费国产传媒海量视频 | 欧洲亚洲日韩中文字幕首页 | 欧美日产国产首 | 最新国产一区二区三区在线 | 欧美精品人在线观看 | 国产日产 | 国产自在自线精品午夜视频 | 欧美午夜在线观看 | 欧美日韩亚洲中文字幕三 | 色爱综合区 | 欧美日韩国产高清 | 极品一区二区三 | 日韩亚欧美一二三四视频 | 精品国产v | 三级国产短视频在线观看 | 国产亚洲欧美另类一区 | 国产日韩a视频在线播放视频 | 国产自产拍精品视频免费看 | 欧美成成人免费 | 中文字幕亚洲无线码一区女同 | 国产午夜亚洲精品不卡免下载 | 国产精品视频第一区二区三区 | 在线观看国产人视频免费中国 | 国产视频美女精品福利社 | 精品国产免费人成电影在线看 | 日日摸夜夜添欧美一区 | 大陆老熟女洗澡性视频tube | 亚州激情视频 | 欧美午夜一区二区三区 | 亚洲熟女综合一区二区三区 | 欧美视频人人干人人 | 国产精品yy| 国拍在线精品 | 好吊妞国产欧美日韩免费观看 | 欧美亚洲综 | 国产亚洲一区激情小说 | 在线播放国产一区 | 国产字幕制服中文在线 | 亚洲熟女丰满多毛xxxxx | 精品国产9 | 日韩激情国产 | 国产精品hd在线播放 | 一区二区视频在线观看 | 精品国内一区二区三区免费视频 | 99re在线这| 亚洲一区二区三区在线观看播放 | 国产又粗又猛 | 日本大胆一区二区三区 | 日本一夲道dvd在线 在线观看国产一线天木耳奈奈 | 国产香港日本三级在线 | 国产99视频精品免费视 | 日韩v亚洲v欧美v精品综合 | 影视网址| 夜鲁夜鲁很鲁在线视频视频 | 一区二区三区四区糖心 | 中文字幕日本精品一区二区三区 | 欧美激情一区二区三级高清视频 | 精品欧美在 | 丝袜亚洲精品中文字幕二区 | 最新高清电影免费在线观看下载 | 三级国产国语三级在线2 | 色综合视频一区二区三区 | 中文字幕按摩做爰 | 性刺激的 | 亚洲欧美日韩综合在线 | 精品日韩成人欧美 | 国产婷婷综合在线视频 | 亚欧视频在线观 | 91精品国产闺蜜国产在 | 国产精品1024香蕉在线观看 | 亚洲国产精品青青网 | 国产精品一级国产精品片 | 巨臀中文字幕一区二区 | 国产剧情自创在线播放 | 亚洲精品色午夜 | 91精品国产一区二区三区香蕉 | 一区二区三区影院在线午夜 | 一区二区三区免费视频 | 国产精品日韩专区第一页 | 国内20| 国产精品第一二三区 | 在线观看网站国产精品 | 99国产清国产精品国产 | 免费动漫成本人视频网站 | 国精一二二产品无人区 | 午夜私人成年影院在线观看 | 亚洲香蕉国产高清在线播放 | 最新电影电视剧 | 日韩中文字幕亚洲精品 | 含羞草国产亚洲精品岁国产精品 | 一级a性色生活片 | 91福利国产在线在线播放 | 国产精品天天看特色大片 | 国产欧美亚 | 97色伦| 欧美亚洲色另类偷自拍 | 日产国产精品日韩精品 | 日韩不卡在线视频 | 欧美日韩变态另类在线观看 | 午夜性爽一区二区三区 | 国产夜夜爽 | 国产精品妇| 亚洲欧美在线观看片不卡 | 欧美+日韩+中文字幕 | 综合精品 | 日本免费一二区 | 国产精品福利片免费看 | 国产一区二区三区自产 | 欧美精品自拍一区 | 97国产综合色产在线视频 | 亚洲高清在线观 | 亚洲精品国产va在线观看天堂 | 日本一本二本三区免费免费高清 | 国产自偷酒店在线观看 | 亚洲精品老司机综合影院 | 欧美一区二区不卡视频 | 青青91视频 | 天堂资源中文 | 在线观看中文字幕码 | 国产一区二区亚洲一区二区 | 日本一区二区三区视频在线观看 | 国产精选污视频在线观看 | 国产一区二区三区视频在线观看 | 国产一区二区三区不卡在线看 | 国产欧美日本不卡 | 电影天堂 | 护士在办公室被躁bd在线观看 | 亚洲成a人片在线观看高清 在线观看www成人影院 | 欧美日韩欧美 | 精品国产欧美在线小说区 | 不卡日韩中文字幕在线观看 | 免费日韩电影网 | 国产精品资源网站视频 | 国产精品天干天干综合网 | 美女被肏翻白眼视频在线观看 | 亚洲永久 | 成人欧美日韩一区 | 国产在线精品国自产拍影院午夜 | 欧美a级成人 | 黑人精品一区二区三区不卡 | 亚洲免费人成 | 精品国产一区二区三区四 | 日韩欧美国产另 | 日韩免费高清大片在线 | 制服丝袜在线手机国产 | 福利100合集在线播放 | 色综合天天综合网国产国产人 | 亚洲中文字幕a∨在线 | 欧美巨大巨粗黑人性aaaaaa | 黑人巨大精品欧美一区二区 | 午夜三级| 免费片在线观看 | 日韩在线视频www色 午夜福利在线观看亚洲一区二区 | 亚洲欧洲中文字幕 | 精品国产蜜桃臀在线观看 | 亚洲视频永久在线 | 亚洲人午夜射精精 | 亚洲精品亚洲人成在线播放 | 亚洲欧洲中文字 | 亚洲成国产人片在线观看 | 成人国产精品日本在线 | 在线免费观看成年人视频 | 日韩成人国产精品视频 | 国产又粗又硬又大爽黄老大爷视 | 91国内精品线免费播放 | 日韩精品中文字幕一区 | 日韩一区二区三区四区中文字幕 | 欧美精品网站一区二区三区 | 国产精品色内内在线播放 | 亚洲人成中文字幕在线观看 | 日本精品一区二区三区在线 | 91国偷自产中文字幕婷婷 | 海量热播电视剧手机电影在线观看 | 日本动漫在线 | 手机看片国产欧美日韩 | 免费动漫网站 | 亚洲精国产一区二区三区 | 不卡视频一区二区三区免费观看 | 自拍偷在 | 永久免费精品性爱网站 | 欧美性白人极 | 国产精品视频免费看人鲁 | 精品蜜桃秘?一区二区三区 成人年鲁鲁在线观 | 福利微拍一区二区 | 国产在线一区二区三区不卡在线 | 高清在线观看视频 | 免费国产污网站在线观看 | 日韩中文字幕高清在线 | 国产99视频精品免视看9 | 中文日本免费高清 | 成a人片免费在线观看 | 一本到在线观看视频 | 亚洲欧美综合一区二区三区黄大片 | 欧美一区二区精品系列在线观看 | 91影视永久福 | 亚洲欧美综合视频 | 亚洲欧美日韩精品中文乱码 | 日本在线在线亚洲 | 91福利国产午夜亚洲精品 | 国产日韩综合精品一区二区三区 | 成人精品一区二区三区免费观看 | 国产亚洲午夜高清国产拍精品 | 国产亚洲精品拍拍拍拍拍 | 2025免费国产a| 亚洲和欧洲一码二码区别在 | 日本免费一区二区在线看片 | 日韩色视 | 在线免费视频成人 | 两性色午夜视频免费国产 | 国产在线高清精品1314 | 日本在线综合一区二区三区 | 国产系列丝袜熟女精品网站 | 大陆国产精品 | 亚洲日本在线在线看片4k超清 | 在线观看网站国产精品 | 亚洲曰韩精 | 国产精品一区二区日韩91 | 国产伦精品一区二区三区视 | 呦交小u女国产 | 日本vs亚洲vs韩国一区三区 | 在线观看国产亚洲自拍 | 青青青国产在线观看 | 乱伦三级高清精 | 精品a视频在线观看 | 国产不卡福利片在 | 国产人妖ts重口系列网站观看 | 亚洲欧美在线观看片不卡 | 果冻传媒mv国产推荐视频 | 在线免费观看国 | 亚洲欧美中文日韩aⅴ | 国产午夜福利一区二区三区在 | 免费激情网站国产高清第一页 | 最新免费电影 | 最新好看的影视大全在线观看 | 亚洲欧美另类 | 国产在线一区二区三区视频 | 日产精品二线三线 | 亚洲精品日韩精品一区 | 国产一区二区三区丝袜精品 | 欧美激情一区二区三级高清视频 | 日本一卡二卡三 | 最新热门电影电视剧免费在线观看 | 日产精品卡2卡3卡4卡免费 | a在线观看 | 国产日产亚洲欧美综合另类 | 亚洲高清无 | 精品精品国产自 | 成人免费网站又大又黄又粗 | 国产国产 | 欧美性猛交xxxx免费看 | 国产精品亚洲一区二区在线观看 | 果冻文化传媒官网 | 综合三级中| 国产一区二区三区激情四射 | 国内精品人| 欧美精品区 | 国产自国产自愉自愉免费24区 | 伊人焦久综合影院每日更新 | 国产高清自偷自 | 在线观看亚洲一区二区三区 | 亚洲日韩精品欧美一区二区 | 国产一区二区三区激情四射 | 国产精品99精品 | 欧美xx在线 | 日本欧美三级成人精品 | 日本91视频 | 精品国语任你躁 | 天美传媒在线观看果 | 91丝袜足| www.尤物在线 | 手机免费在线观看日韩电影 | 精品国产污污免费网站入口 | 巨臀中文字幕一区二区 | 日韩色在线影院性色 | a在线观看 | 在线成人精品国产区免费 | 亚洲精品在线观看视频 | 请放心下载! | 亚洲国产在线精品国偷产拍 | 日本女一区二 | 国产v片在线播放免费观看大全 | 中文日本不卡二区 | 网友自拍露脸国语对白 | 亚洲午夜一区二区三区在线观看 | 亚洲免费在线国产视频午夜精 | 亚洲一区二区三区不卡视频 | 传媒视频免费在线 | 亚洲愉拍自拍另类 | 91福利国产在线观看香蕉 | 成年人免费在线看的惊悚动作片 | 国产精品高清免费网站电影 | 高清午夜福利电影在线 | 成人黄性视频 | 亚洲国产日韩欧 | 免费人成黄页网站大全在线观 | 五月丁六月停停 | 激情亚洲一区国 | 欧美一区日韩一区中文字幕页 | 日韩无砖专 | 在线人成观看 | 十大黄台禁用 | 九九热99久| 亚洲一级影院 | 国产精品不卡一区二区 | 电话耳麦 | 91精品手机国产在线观 | 2025国产品在线视频不卡不卡 | 加勒比精品 | 中韩欧美视频一区 | 999二区在线 | 星光影院| 国语自产免费精品视频在 | 人人精品午夜视频 | 国产精品人成 | 欧美不卡在线 | 亚洲国产欧美日韩另类 | 日本在线观看的免费 | 日本天堂天v在线播放 | 国产精品国语对白露脸在线播 | 国产一区日韩 | 亚洲国产日韩欧美一区二区三区 | 国产午夜福利 | 国产思思精品视频 | 亚洲欧美极品 | 国产欧美网站 | 亚洲精品国产精品精 | 老司机免费精品线观看86 | 国产精品v一区 | 96精品专区国产在线观看高清 | 亚洲日本v中文字幕区 | 设看到很多欧美日韩一区二区综 | 中文字幕自拍偷拍 | 精品国内一区二区三区免费 | 亚洲国内自拍愉拍中文字幕 | 国产精品福利在线观看免费 | 加勒比一本大道香蕉大在线 | 欧美日本国 | 好吊妞国产欧美日韩免费观看 | 欧美日韩精品系列一区二区三区 | 欧美人一级淫片a免费播放 国产精品永久免费自在线观 | 91香蕉国产观看免费人人 | 激情综合在线亚洲五月天 | 亚洲精品国产精品精 | 欧美午夜一区二区三区 | 国产精品va尤物在线观看 | 国产高清www免费视频 | 国产一区二区精品免费播放 | 国产日韩高清一区二区三区 | 欧美午夜一区二区之蜜桃 | 亚洲自偷精品视频自拍 | 不止不休高清在线观看 | 国产欧美精品亚洲日本一区 | 国产欧美日本韩国另类 | 国产精品涩涩涩视频网站 | 国产每日更 | 韩国美女一区二区 | 中文字幕精品视频第一区第二 | 亚洲精品成人a | 国产乱码日产精品bd | 红杏免费视频网站入口导航 | 亚洲日韩欧美一区二区在线 | 欧美日韩视频一区二区三区 | 国产精品一级婬片免费 | 最新电影电 | 欧美在线综合 | 免费h在线观看视频网站 | 99re热这里只有精品视频 | 免费一级欧美大片在 | 97se亚洲精品一区 | 国产精品偷窥熟女欧美激 | 1卡2卡三卡4卡国产 欧美日韩精品一区二区在线 | 国产亚洲老 | 亚洲一区二区三区不卡精品 | 亚洲偷自拍另类图片二区 | 香港三日本三级人妇三级99 | 捆绑视频 | 国产精品国内免费一区二区三区 | 日本一区二区三区在线播放 | 国产91玉足脚交在线播放 | 国产一区二区丝袜美腿在线 | 亚洲第一影院中文字幕 | 囯产精品宾馆在线精品酒店 | 欧美性活一级视频 | 甜性涩爱 | 亚洲香蕉综合在人在线视看 | 精品第一国产综合精品蜜芽 | 亚洲日韩一页精品发布 | 国产乱伦视频 | 国产精品a无线 | 亚洲国产日韩不卡线欧美 | 国产一级淫片免费视 | 国产。亚洲。在线播放 | 亚洲欧美国产国产一区二区三区 | 亚洲精品亚洲精品亚洲精品日韩 | 99热这里只有精品18 | 国产三区四区五区 | 18国产午夜福| 国产91页 | 欧美黑人巨大精品一区二区三区 | 九九九九九在线精品区 | 美国精品亚 | 国产在线欧美日韩精品一区 | 中文字幕亚洲欧美色 | 欧美三级蜜桃2在线观看 | 国产视频一区 | 国产永久精品一区二区污污 | 国产女人精品在线直播 | 综合乱伦国产中文 | 亚洲精品乱码在线观看 | 日本欧美韩国一区二区三区 | 99国产婷婷综合在线视频 | 精品三级视频在线观看 | 国产又黄 | 人人揉揉揉揉揉日日 | 美女爽到尿喷出来 | 国产精品亚洲一区二区在线观看 | 日韩在线观看视频网站 | 国产精品亚洲专区在线观看 | 中文字幕第一页亚洲 | 国产在线精品一区二区不卡顿 | 在线观看中文字幕 | 中文文字幕文字幕亚洲色 | 免费国产在线观看 | 中文字幕手机在线看片不卡 | 亚洲熟女丰满多毛xxxxx | 国产一区二区视频免费 | 全部视频欧美日韩在线无人 | 欧美日韩精品中文字幕 | 国产精品视频每日更新 | 免费特级欧美片 | 亚洲色偷精品一区二区三区 | 91极品美| 亚洲二区在线 | 国产精品免费视频一区二区三区 | 超薄肉色丝袜一区二区 | 免费的影视大全 | 在线美剧天堂 | 国产盗摄偷窥在线观看 | 国产福利91精品一区二区 | 91精品欧美激情在线播放 | 一个人看的免费高清www视频 | 欧美极品欧美精品欧美 | 成视频免费国产 | 国产精品欧美一区二区三区不 | 日韩一区二区免费看 | 国产亚洲a∨片在线观看 | 国产亚洲精品国产 | 91精选日韩综合永久入口 | 91碰超免费观看 | 国产亚洲精品资源在线 | 亚洲欧美综合高清在线 | 亚洲成脛∨人片在线观看福利 | 2025果冻传媒 | 91免费视视频在线观看 | 欧美日韩一区二区三 | 日韩欧美精品一区二区三区在线 | 91福利免费体验区观看区 | 亚洲欧美自| 日韩在线视频一区二区 | 欧美.成人.综合在线 | 免费动漫网站 | 婷婷六月亚洲中文字幕不卡 | 国产精品亚洲综合一区在 | 国产日韩在线视频 | 国产亚洲欧美手机在线观看 | 亚洲成aⅴ人的天堂在线观看女人 | 尤物视频官网 | 91caopor | 午夜性色一区二区三区不卡视频 | 一个人看的www日本高清视频 | 色偷偷中 | 成人污污污w | 99精品视频在线观看婷婷 | 91电影在线观看 | 欧美a级毛欧美1级a大片式放 | aaaaa级少| 国产一区二区三区四区精 | 精品国产女主播在线观看 | 有码在线观看免费 | 加勒比he| 免费一区二区三区日韩 | 99热在线获取最新地址 | 丁香花在线视频观看免费 | 国产精品99精品一区二区 | 亚洲无人区码卡二卡三卡四卡 | 午夜福利精品在线播放 | 亚洲日韩欧美天堂 | 国产亚洲理论在线观看 | 日韩午夜视频在线观看 | 91看片网站免费看 | 午夜欧美视频 | 成年轻人视频免费视频 | 国产v一区二区综合 | 自拍偷拍欧美图片 | 天美麻花果冻苏蜜清歌 | 欧美又粗又大一区二区 | 天堂中文在线资源 | 国产精品1234| 手机在线看电影的网站 | 日韩精品福利 | 国产精品网站不卡在线观看 | 国产亚洲精品片a77777 | 亚洲天堂网一区二区三区四区 | 国产在线不卡精品网站互動交 | 在线观看亚洲欧美日本 | 国产福利在线观看极品美女 | 三年片免费观看大全 | 国产精品蜜桃丝袜 | 人人香蕉 | 日本一区二区三区四区不卡 | 中文字幕一区二区三区 | 2025精品国产自在现线看 | 国产精品永久免费视频观看 | 日本乱理伦片在线观 | 国产精品丝袜亚洲熟女 | 手机在线| 五月天久 | 国产精品极品美女自在线观看 | 成人日动漫卡一区二区三区动漫 | 欧美a√在线免费观看 | 国产午夜福利免费看片 | 午夜影视污 | 日本精品高清一区二区 | 欧美日韩精品一区二区视频 | 国产精品一区二区在线观看网站 | 欧美精品亚洲日韩aⅴ | 国产精品亚洲日韩au在线 | 国产午夜电影在线电影 | 天美麻花果冻视频大全 | 国产一区二区在线 | 成人欧美精品资源在线观看 | 精品国语自产拍在线观看 | 网曝精品视频在线 | 日韩乱码人 | 亚洲欧美一区二区三区久本道 | 日本欧美高清全视频 | 国产在线精品一区二区在线看 | 97在线观看高清视频免费 | 国产资源中文字幕 | 国产精品露脸国 | 乌克兰18极品xx00喷水 | 一出一进一爽一粗一大视频免 | 亚洲欧美中文高清在线 | 色橹橹欧美在线观看视频高清 | 青草青草久热精品视频在线播放 | 国产精品一区成人精品果冻传媒 | 免费国产黄线在线播放 | 国产精品天天天天影视 | 91精品国产亚一区二区三区 | 三级国产久 | 日韩欧美国产一区二区三 | 老子影院午夜伦不卡亚洲 | 国产欧美日韩不卡一区二区 | 人善交vi | 欧美v亚洲v综合ⅴ国产v | 国产一区欧美一区二区 | 成人国产在线 | 永久免费精品影视网站 | 国产精品碰碰现在自在拍 | 尤物免费人成在线观看播放a | 中文字幕亚洲网址 | 44极品视频在| 迷奷系列在线播放456 | 国产真实乱xxxⅹ视频 | 国产精品自产拍高 | 蜜桃臀aⅴ精品一 | 国产97在线 | 亚洲欧美另类在线视频 | 亚洲大片精品免费在线 | 一二三四在线观看免费中文吗中文 | 国产一区二区 | 日本三级日产三级国 | 国产乱色国产精品免费视频 | 国产理论视频在线观看 | 无玛专区 | 日韩一区二区三区免费播放 | 男女日皮视频app | 欧洲乱码伦网站 | 亚洲一区二区三区四区视频 | 在线亚洲一区二区三区四区 | 国产色系视频在线观看免费 | 国产午夜视频在线 | 亚洲精品aⅴ中文字幕乱码 国产在线ts | 国产在线高清精品三区 | 九九热精品在 | 精品亚洲成a人在线看片 | 天堂中文最新版在线中文 | 91免费短 | 亚洲一区高清 | 欧洲一卡2 | 漂亮大学| 九九九热在线精品免费全部 | 亚洲中文字幕精品一区二区三区 | 又粗又硬又大又黄又爽的免 | 最近中文字幕mv免费高清视频 | 国产精品线在线精品 | 成人国产一区二区三区精品 | 亚洲精品在线免费观看 | 日产精品| 国产女人精品在线直播 | 欧美日韩精品一区二蜜桃在线观 | 三级国产4国语三级在线 | 91精品国产白产91精品 | 韩国在线观看日韩免費資訊 | 在线观看国产 | 国产高清在线精品一区小说 | 2025欧美日韩| 亚洲经典日韩欧美国产一区 | 国产乱子伦农村xxxx | 欧美精品一区二区三区四 | 成人精品一区二区三区免费观看 | 国产女主播勾搭美团在线观看 | 国产欧美视频综合二区 | 国产精偷伦视频在线观看 | 国产原创露脸视频在线观看 | 国产+日韩精品 | 2025国产精品自在拍在线播放 | 国产福利一区二区久 | 视频在线观看不卡免费 | 最新国产福利在 | 最近中文字幕高清mv免费 | 日本欧美午夜三 | 91精品国产aⅴ一区二区 | 午夜一区二区免 | 国产在线观看第二十三页 | 亚洲欧美日本v | 亚洲国产精品国语在线 | 精品国产综合色在线 | 加勒比一本大道香蕉大在线 | 放荡老师张开双腿任我玩 | 国产高清国内精品 | 国产美女一区二区丝袜美腿 | 青青青国产爽爽视频免费观看 | 国产精品亚洲片在线观看不卡 | 60老熟女多次高 | 亚洲人成电影网站国产精品 | 国产老女人精品免费视频 | 色两性午夜视频免费观看 | 亚洲色偷偷综合亚洲 | 午夜亚洲理 | 国产a∨精品一区二区三区不 | 中文无字幕一 | 国产伦理片在线观看 | 精品国产高清自在线一区二区三区 | a级国产乱理伦 | 亚洲欧美中文一区二区三区 | 亚洲韩精品欧美一区二区三区 | 中文免费高清特 | 最好看免费观看高清电影大全 | 电视剧大全手机 | 国产免费一区二区三区在线看 | 青青草免费国产视频网站 | 欧美亚洲一区二区三区三 | 国产日本一线在线观看免费 | 国产人妇三级视频在线观看 | 日韩四色在线视频观看网站 | 亚洲欧洲美 | 国产欧美精品国产国产专区 | 不卡兔费 | 精品日韩欧美一区二区在线播放 | 鲁丝片一区二区三区免费 | 国一产区视频 | 免费最新电视剧 | 国产午夜手 | 亚洲精品1卡2卡三卡23卡 | 91国在线精品国内播放 | 欧美黑人ⅹxxx猛交 日日狠狠 | 专区网站 | 国产免费人成 | 欧美日韩中 | 福利一区二区三区视频在线观看 | 亚洲免费无| 日本一区二区三区免费在线观看 | 欧美日韩国产成 | 日韩r级电影在线观看 | 精品国产福利第一区二 | 不用下载播放器的电影网 | 国产精选免 | 成人免费高清观看在线 | 国产一区二区高清 | 国产亚洲精品福利片 | 亚洲精品高清在线观看 | 国产欧美日韩va另类在 | 亚洲+欧洲+日产 | 国产精品视频国产永久视频 | 日韩高清在线观看不卡一区二区 | 十分钟在线观看免费直播 | 亚洲一区二区自 | 三级国产短视频在线观看 | 国内女人喷潮完整视频 | 国内三级自 | 中文字幕免费高清电视剧网站 | 成人欧美一区二区三区在线观看 | 国产精品色一区二区三区 | 亚洲一本大道中文在线 | 亚洲综合欧美日韩国产一区二区桃 | 无限国产资源好片2025 | 国产在线精品国自产拍影院同性 | 一本一本大道香蕉久在线精品 | 国产农村妇女精品一二区 | 人人狠狠综合99综合久 | 午夜日韩综合激 | 亚洲欧美一区二区三区在线 | 欧美日韩免费专区在线 | 日本a优不卡在线播放 | 国产福利爱福利微拍视频 | 国产偷国产偷精品孕妇 | 精品h一区不卡免费视频国产 | 国产亚洲人成a在线v网站 | 九九热精品视频在线观看 | 91青青草原 | 国产制服丝袜亚洲高清 | 中文字幕精品一区二区三区在线 | 免费在电影在线观看 | 亚洲ⅴa在线观看 | 欧美xxxx欧美精品 | 极品魔鬼身 | 国产免费中文字幕v在线 | 国产在线一区二区播放精品 | 国产乱码1卡二卡3卡四卡5 | 91免费国产高清在线 | 99ri日韩精品视频 | 日产精品卡2卡3卡4卡免费 | 伊人网视频在线观看 | 亚洲国产免费 | 日韩欧美亚洲一区二区在线观看 | 亚洲精品乱码久 | 午夜福利成人污在线观看 | 国产精品高清自产拍 | 亚洲激情 | 最新91精品老司机在线 | 免费一级e一片在线播放 | 免费手机影院 | 变态拳头交视频一区二区 | 免费人成年激情视频在线观看 | 大地资源中文第二页高清 | 在线精品自拍亚洲第一区 | 最新欧美日韩 | 欧美日韩一区二区不卡在线播放 | 99在线观看 | 国产精品va在线播放我和闺蜜 | 日韩专区在线观看 | 亚洲国产日韩一级精品视频网站 | 亚洲色大成网站www在线观看 | 日本女优一区二区三区四区 | 欧美一卡2卡3卡4卡新区 | 成人精品视频一区二区三区 | 免费人成在线观看视频品爱网 | 搡老女人露脸 | 中年熟女乱子正在播放 | 免费国产自线拍 | 乱无伦码中文视频在线 | 无人视频免费观看免费视频 | 在线欧美日韩精品一区二区 | 蜜桃视频一 | 日韩一区二区三区高清中文字幕 | 久热精品视频在线播放 | 欧美中文字幕人成在线网站 | 国产视频精品免费 | 日本免费一二区 | 国产精品第一二三区 | 日韩精品中文字幕一区 | 五月天亚洲欧美激 | 97国语精品自产拍在线观看一 |