Kurumsal Uygulama Gezintisi
Not
Bu e-Kitap 2017 baharında yayımlanmıştır ve o zamandan beri güncelleştirilmemiştir. Kitapta değerli kalan çok şey var, ancak bazı malzemeler güncelliğini yitirmiş.
Xamarin.Forms , genellikle kullanıcının kullanıcı arabirimiyle etkileşiminden veya iç mantık temelli durum değişikliklerinin bir sonucu olarak uygulamanın kendisinden kaynaklanan sayfa gezintisi desteği içerir. Ancak, aşağıdaki zorlukların karşılanması gerektiğinden, gezintinin Model-View-ViewModel (MVVM) desenini kullanan uygulamalarda uygulanması karmaşık olabilir:
- Görünümler arasında sıkı bağlama ve bağımlılıklar içermeyen bir yaklaşım kullanarak, gidilecek görünümü tanımlama.
- Gidilecek görünümün örneği oluşturulup başlatıldığı işlemi koordine etme. MVVM kullanılırken görünüm ve görünüm modelinin örneği oluşturulup görünümün bağlama bağlamı aracılığıyla birbiriyle ilişkilendirilmesi gerekir. Bir uygulama bağımlılık ekleme kapsayıcısı kullanırken görünümlerin ve görünüm modellerinin örneğini oluşturmak için belirli bir yapı mekanizması gerekebilir.
- İlk görüntüleme gezintisi mi yoksa model öncelikli gezintiyi mi görüntüleyebileceğiniz. Görünüm öncelikli gezintide, gidecek sayfa görünüm türünün adına başvurur. Gezinti sırasında, belirtilen görünüme karşılık gelen görünüm modeli ve diğer bağımlı hizmetlerle birlikte örnek oluşturulur. Alternatif bir yaklaşım, model öncesini görüntüleme gezintisini kullanmaktır; burada gidileceği sayfa, görünüm modeli türünün adına başvurur.
- Uygulamanın gezinti davranışını görünümler arasında temiz bir şekilde ayırma ve modelleri görüntüleme. MVVM düzeni, uygulamanın kullanıcı arabirimiyle sunusu ve iş mantığı arasında bir ayrım sağlar. Ancak, bir uygulamanın gezinti davranışı genellikle kullanıcı arabirimine ve uygulamanın sunu bölümlerine yayılır. Kullanıcı genellikle bir görünümden gezinti başlatır ve gezintinin bir sonucu olarak görünüm değiştirilir. Ancak, gezintinin genellikle görünüm modeli içinden başlatılması veya koordine edilmesi gerekebilir.
- Başlatma amacıyla gezinti sırasında parametreleri geçirme. Örneğin, kullanıcı sipariş ayrıntılarını güncelleştirmek için bir görünüme giderse, doğru verileri görüntüleyebilmesi için sipariş verilerinin görünüme geçirilmesi gerekir.
- Belirli iş kurallarına uyulmasını sağlamak için gezintiyi koordine etme. Örneğin, kullanıcılardan bir görünümden ayrılmadan önce, geçersiz verileri düzeltebilmeleri veya görünümde yapılan veri değişikliklerini göndermeleri veya atmaları istenmesi istenebilir.
Bu bölüm, model öncelikli sayfa gezintisini görüntülemek için kullanılan bir NavigationService
sınıf sunarak bu zorlukları ele alır.
Not
NavigationService
Uygulama tarafından kullanılan, yalnızca ContentPage örnekleri arasında hiyerarşik gezinti gerçekleştirmek için tasarlanmıştır. Hizmeti kullanarak diğer sayfa türleri arasında gezinmek beklenmeyen davranışlara neden olabilir.
Sayfalar Arasında Gezinme
Gezinti mantığı, bir görünümün arka planında veya veriye bağlı görünüm modelinde bulunabilir. Gezinti mantığını bir görünüme yerleştirmek en basit yaklaşım olsa da, birim testleri aracılığıyla kolayca test edilemez. Görünüm modeli sınıflarında gezinti mantığı yerleştirmek, mantığın birim testleri aracılığıyla kullanılabilmesi anlamına gelir. Ayrıca görünüm modeli, belirli iş kurallarının uygulandığından emin olmak için gezintiyi denetlemek için mantık uygulayabilir. Örneğin bir uygulama, girilen verilerin geçerli olduğundan emin olmadan kullanıcının sayfadan uzaklaşmasına izin vermeyebilir.
Test NavigationService
edilebilirliği artırmak için genellikle görünüm modellerinden bir sınıf çağrılır. Ancak görünüm modellerinden görünümlere gitmek için görünüm modellerinin görünümlere ve özellikle etkin görünüm modelinin ilişkilendirilmediği görünümlere başvurması gerekir ve bu önerilmez. Bu nedenle, NavigationService
burada sunulan görünüm modeli türünü gidecek hedef olarak belirtir.
eShopOnContainers mobil uygulaması, model öncelikli görüntüleme gezintisi NavigationService
sağlamak için sınıfını kullanır. Bu sınıf, aşağıdaki kod örneğinde gösterilen arabirimini uygular INavigationService
:
public interface INavigationService
{
ViewModelBase PreviousPageViewModel { get; }
Task InitializeAsync();
Task NavigateToAsync<TViewModel>() where TViewModel : ViewModelBase;
Task NavigateToAsync<TViewModel>(object parameter) where TViewModel : ViewModelBase;
Task RemoveLastFromBackStackAsync();
Task RemoveBackStackAsync();
}
Bu arabirim, uygulayan bir sınıfın aşağıdaki yöntemleri sağlaması gerektiğini belirtir:
Yöntem | Purpose |
---|---|
InitializeAsync |
Uygulama başlatıldığında iki sayfadan birine gezinti gerçekleştirir. |
NavigateToAsync |
Belirtilen sayfaya hiyerarşik gezinti gerçekleştirir. |
NavigateToAsync(parameter) |
Bir parametre geçirerek belirtilen bir sayfaya hiyerarşik gezinti gerçekleştirir. |
RemoveLastFromBackStackAsync |
Önceki sayfayı gezinti yığınından kaldırır. |
RemoveBackStackAsync |
Önceki sayfaların tümünü gezinti yığınından kaldırır. |
Ayrıca, INavigationService
arabirim uygulayan bir sınıfın bir PreviousPageViewModel
özellik sağlaması gerektiğini belirtir. Bu özellik, gezinti yığınındaki önceki sayfayla ilişkili görünüm modeli türünü döndürür.
Not
Bir INavigationService
arabirim genellikle gezinti yığınındaki önceki sayfaya program aracılığıyla dönmek için kullanılan bir GoBackAsync
yöntem de belirtir. Ancak gerekli olmadığından eShopOnContainers mobil uygulamasında bu yöntem eksik.
NavigationService Örneği Oluşturma
NavigationService
Arabirimini uygulayan INavigationService
sınıfı, aşağıdaki kod örneğinde gösterildiği gibi Autofac bağımlılık ekleme kapsayıcısı ile tekil olarak kaydedilir:
builder.RegisterType<NavigationService>().As<INavigationService>().SingleInstance();
Arabirim INavigationService
, aşağıdaki kod örneğinde ViewModelBase
gösterildiği gibi sınıf oluşturucusunda çözümlenir:
NavigationService = ViewModelLocator.Resolve<INavigationService>();
Bu, sınıfındaki NavigationService
yöntemi tarafından oluşturulan Autofac bağımlılık ekleme kapsayıcısında depolanan nesneye InitNavigation
App
bir başvuru döndürür. Daha fazla bilgi için bkz . Uygulama Başlatıldığında Gezinme.
ViewModelBase
sınıfı örneği türünde INavigationService
bir NavigationService
özellikte depolarNavigationService
. Bu nedenle, sınıfından ViewModelBase
türetilen tüm görünüm modeli sınıfları, arabirimi tarafından INavigationService
belirtilen yöntemlere erişmek için özelliğini kullanabilirNavigationService
. Bu, autofac bağımlılık ekleme kapsayıcısından nesneyi her görünüm modeli sınıfına ekleme yükünü NavigationService
önler.
Gezinti İsteklerini İşleme
Xamarin.Forms , kullanıcının sayfalarda NavigationPage
, ileri ve gerilerde istediği gibi gezinebileceği hiyerarşik bir gezinti deneyimi uygulayan sınıfını sağlar. Hiyerarşik gezinti hakkında daha fazla bilgi için bkz . Hiyerarşik Gezinti.
eShopOnContainers uygulaması, sınıfı doğrudan kullanmak NavigationPage
yerine aşağıdaki kod örneğinde CustomNavigationView
gösterildiği gibi sınıfını sınıfta sarmalarNavigationPage
:
public partial class CustomNavigationView : NavigationPage
{
public CustomNavigationView() : base()
{
InitializeComponent();
}
public CustomNavigationView(Page root) : base(root)
{
InitializeComponent();
}
}
Bu sarmalamanın amacı, sınıfı için XAML dosyasının NavigationPage
içindeki örneği şekillendirmeyi kolaylaştırmaktır.
Gezinti, aşağıdaki kod örneğinde gösterildiği gibi yöntemlerden biri NavigateToAsync
çağrılarak, gidilmekte olan sayfanın görünüm modeli türü belirtilerek görünüm modeli sınıflarının içinde gerçekleştirilir:
await NavigationService.NavigateToAsync<MainViewModel>();
Aşağıdaki kod örneği, sınıfı tarafından NavigationService
sağlanan yöntemleri gösterirNavigateToAsync
:
public Task NavigateToAsync<TViewModel>() where TViewModel : ViewModelBase
{
return InternalNavigateToAsync(typeof(TViewModel), null);
}
public Task NavigateToAsync<TViewModel>(object parameter) where TViewModel : ViewModelBase
{
return InternalNavigateToAsync(typeof(TViewModel), parameter);
}
Her yöntem, sınıfından ViewModelBase
türetilen herhangi bir görünüm modeli sınıfının yöntemini çağırarak hiyerarşik gezinti gerçekleştirmesine InternalNavigateToAsync
olanak tanır. Buna ek olarak, ikinci NavigateToAsync
yöntem gezinti verilerinin genellikle başlatma gerçekleştirmek için kullanıldığı görünüm modeline geçirilen bir bağımsız değişken olarak belirtilmesine olanak tanır. Daha fazla bilgi için bkz . Gezinti Sırasında Parametreleri Geçirme.
InternalNavigateToAsync
yöntemi gezinti isteğini yürütür ve aşağıdaki kod örneğinde gösterilir:
private async Task InternalNavigateToAsync(Type viewModelType, object parameter)
{
Page page = CreatePage(viewModelType, parameter);
if (page is LoginView)
{
Application.Current.MainPage = new CustomNavigationView(page);
}
else
{
var navigationPage = Application.Current.MainPage as CustomNavigationView;
if (navigationPage != null)
{
await navigationPage.PushAsync(page);
}
else
{
Application.Current.MainPage = new CustomNavigationView(page);
}
}
await (page.BindingContext as ViewModelBase).InitializeAsync(parameter);
}
private Type GetPageTypeForViewModel(Type viewModelType)
{
var viewName = viewModelType.FullName.Replace("Model", string.Empty);
var viewModelAssemblyName = viewModelType.GetTypeInfo().Assembly.FullName;
var viewAssemblyName = string.Format(
CultureInfo.InvariantCulture, "{0}, {1}", viewName, viewModelAssemblyName);
var viewType = Type.GetType(viewAssemblyName);
return viewType;
}
private Page CreatePage(Type viewModelType, object parameter)
{
Type pageType = GetPageTypeForViewModel(viewModelType);
if (pageType == null)
{
throw new Exception($"Cannot locate page type for {viewModelType}");
}
Page page = Activator.CreateInstance(pageType) as Page;
return page;
}
yöntemi, InternalNavigateToAsync
önce yöntemini çağırarak görünüm modeline CreatePage
gezinti gerçekleştirir. Bu yöntem, belirtilen görünüm modeli türüne karşılık gelen görünümü bulur ve bu görünüm türünün bir örneğini oluşturur ve döndürür. Görünüm modeli türüne karşılık gelen görünümü bulmak için kural tabanlı bir yaklaşım kullanılır ve bu yaklaşım şunları varsayar:
- Görünümler, görünüm modeli türleriyle aynı derlemededir.
- Görünümler bir içindedir. Alt ad alanını görüntüler.
- Görünüm modelleri bir içindedir. ViewModels alt ad alanı.
- Görünüm adları, "Model" kaldırılmış şekilde model adlarını görüntülemeye karşılık gelir.
Bir görünümün örneği oluşturulurken ilgili görünüm modeliyle ilişkilendirilir. Bunun nasıl gerçekleştiği hakkında daha fazla bilgi için bkz . Görünüm Modeli Bulucu ile Otomatik Olarak Görünüm Modeli Oluşturma.
Oluşturulan görünüm bir LoginView
ise, sınıfın yeni bir örneğine CustomNavigationView
sarmalanır ve özelliğine Application.Current.MainPage
atanır. Aksi takdirde, CustomNavigationView
örnek alınır ve null değilse, PushAsync
oluşturulan görünümü gezinti yığınına göndermek için yöntemi çağrılır. Ancak, alınan CustomNavigationView
örnek ise null
, oluşturulan görünüm sınıfın CustomNavigationView
yeni bir örneğinde sarmalanır ve özelliğine Application.Current.MainPage
atanır. Bu mekanizma, gezinti sırasında sayfaların hem boş olduğunda hem de veri içerdiğinde gezinti yığınına doğru şekilde eklenmesini sağlar.
İpucu
Sayfaları önbelleğe almayı göz önünde bulundurun. Sayfa önbelleğe alma, şu anda görüntülenmeyen görünümler için bellek tüketimine neden olur. Ancak, sayfa önbelleğe alınmadan, XAML ayrıştırma ve sayfanın yapısı ile görünüm modelinin her yeni sayfaya gidildiğinde gerçekleşeceği ve bu da karmaşık bir sayfa için performans etkisi yaratabileceği anlamına gelir. Aşırı sayıda denetim kullanmayan iyi tasarlanmış bir sayfa için performans yeterli olmalıdır. Ancak sayfa önbelleğe alma işlemi, yavaş sayfa yükleme süreleri ile karşılaşıldığında yardımcı olabilir.
Görünüm oluşturulduktan ve konumuna gidildikten sonra, InitializeAsync
görünümün ilişkili görünüm modelinin yöntemi yürütülür. Daha fazla bilgi için bkz . Gezinti Sırasında Parametreleri Geçirme.
Uygulama Başlatıldığında Gezinme
Uygulama başlatıldığında, sınıfındaki InitNavigation
App
yöntemi çağrılır. Aşağıdaki kod örneği bu yöntemi gösterir:
private Task InitNavigation()
{
var navigationService = ViewModelLocator.Resolve<INavigationService>();
return navigationService.InitializeAsync();
}
yöntemi, Autofac bağımlılık ekleme kapsayıcısında yeni NavigationService
bir nesne oluşturur ve yöntemini çağırmadan InitializeAsync
önce buna bir başvuru döndürür.
Not
INavigationService
Arabirim sınıfı tarafından ViewModelBase
çözümlendiğinde kapsayıcı, InitNavigation yöntemi çağrıldığında oluşturulan nesneye bir başvuru NavigationService
döndürür.
Aşağıdaki kod örneği yöntemini gösterir NavigationService
InitializeAsync
:
public Task InitializeAsync()
{
if (string.IsNullOrEmpty(Settings.AuthAccessToken))
return NavigateToAsync<LoginViewModel>();
else
return NavigateToAsync<MainViewModel>();
}
MainView
, uygulamanın kimlik doğrulaması için kullanılan önbelleğe alınmış bir erişim belirteci varsa adresine gider. Aksi takdirde, LoginView
öğesine gider.
Autofac bağımlılık ekleme kapsayıcısı hakkında daha fazla bilgi için bkz . Bağımlılık Eklemeye Giriş.
Gezinti Sırasında Parametreleri Geçirme
NavigateToAsync
Arabirim tarafından belirtilen yöntemlerden biri, gezinti verilerinin INavigationService
genellikle başlatma gerçekleştirmek için kullanıldığı görünüm modeline geçirilen bir bağımsız değişken olarak belirtilmesine olanak tanır.
Örneğin, sınıfı, ProfileViewModel
kullanıcı sayfadan bir OrderDetailCommand
sipariş ProfileView
seçtiğinde yürütülen bir içerir. Bu da aşağıdaki kod örneğinde gösterilen yöntemini yürütür OrderDetailAsync
:
private async Task OrderDetailAsync(Order order)
{
await NavigationService.NavigateToAsync<OrderDetailViewModel>(order);
}
Bu yöntem, kullanıcının sayfada seçtiği sırayı OrderDetailViewModel
temsil eden bir Order
örnek geçirerek öğesine gezintiyi ProfileView
çağırır. NavigationService
sınıfı öğesini oluşturduğundaOrderDetailView
OrderDetailViewModel
, sınıf örneği oluşturulur ve görünümün BindingContext
öğesine atanır. yöntemi, öğesine gittikten OrderDetailView
InternalNavigateToAsync
sonra görünümün ilişkili görünüm modelinin yöntemini yürütürInitializeAsync
.
InitializeAsync
yöntemi, sınıfında geçersiz kılınabilecek bir yöntem olarak tanımlanırViewModelBase
. Bu yöntem, object
gezinti işlemi sırasında görünüm modeline geçirilecek verileri temsil eden bir bağımsız değişken belirtir. Bu nedenle, bir gezinti işleminden veri almak isteyen model sınıflarını görüntüleme, gerekli başlatmayı gerçekleştirmek için yönteminin kendi uygulamasını InitializeAsync
sağlar. Aşağıdaki kod örneği sınıfından InitializeAsync
yöntemini OrderDetailViewModel
gösterir:
public override async Task InitializeAsync(object navigationData)
{
if (navigationData is Order)
{
...
Order = await _ordersService.GetOrderAsync(
Convert.ToInt32(order.OrderNumber), authToken);
...
}
}
Bu yöntem, gezinti işlemi sırasında görünüm modeline geçirilen örneği alır Order
ve örnekten tam sipariş ayrıntılarını OrderService
almak için kullanır.
Davranışlar Kullanarak Gezintiyi Çağırma
Gezinti genellikle bir kullanıcı etkileşimi tarafından bir görünümden tetikler. Örneğin, başarılı kimlik doğrulamasından LoginView
sonra gezinti gerçekleştirir. Aşağıdaki kod örneği, gezintinin bir davranış tarafından nasıl çağrıldığı gösterir:
<WebView ...>
<WebView.Behaviors>
<behaviors:EventToCommandBehavior
EventName="Navigating"
EventArgsConverter="{StaticResource WebNavigatingEventArgsConverter}"
Command="{Binding NavigateCommand}" />
</WebView.Behaviors>
</WebView>
çalışma zamanında ile EventToCommandBehavior
etkileşime WebView
yanıt verir. WebView
bir web sayfasına gittiği zaman, Navigating
olay tetiklenir ve içinde yürütülür NavigateCommand
LoginViewModel
. Varsayılan olarak, olayın olay bağımsız değişkenleri komutuna geçirilir. Bu veriler, özelliğinde EventArgsConverter
belirtilen dönüştürücü tarafından kaynak ve hedef arasında geçirildikçe dönüştürülür ve bu da dosyasından WebNavigatingEventArgs
değerini Url
döndürür. Bu nedenle, yürütülürken NavigationCommand
, web sayfasının Url'si kayıtlı Action
öğesine parametre olarak geçirilir.
Buna karşılık, NavigationCommand
aşağıdaki kod örneğinde gösterilen yöntemi yürütülür NavigateAsync
:
private async Task NavigateAsync(string url)
{
...
await NavigationService.NavigateToAsync<MainViewModel>();
await NavigationService.RemoveLastFromBackStackAsync();
...
}
Bu yöntem , gezintisini MainViewModel
çağırır ve aşağıdaki gezinti, sayfayı LoginView
gezinti yığınından kaldırır.
Gezintiyi Onaylama veya İptal Etme
Kullanıcının gezintiyi onay edebilmesi veya iptal edebilmesi için bir uygulamanın gezinti işlemi sırasında kullanıcıyla etkileşim kurması gerekebilir. Örneğin, kullanıcı bir veri giriş sayfasını tam olarak tamamlamadan önce gezinmeyi denediğinde bu gerekli olabilir. Bu durumda, bir uygulama kullanıcının sayfadan uzaklaşmasına veya gezinti işlemini gerçekleşmeden önce iptal etmesine olanak tanıyan bir bildirim sağlamalıdır. Bu, gezintinin çağrılıp çağrılmayacağını denetlemek için bir bildirimden gelen yanıt kullanılarak bir görünüm modeli sınıfında elde edilebilir.
Özet
Xamarin.Forms , genellikle kullanıcının kullanıcı arabirimiyle etkileşiminden veya iç mantık temelli durum değişikliklerinin bir sonucu olarak uygulamanın kendisinden kaynaklanan sayfa gezintisi desteği içerir. Ancak, gezintinin MVVM desenini kullanan uygulamalarda uygulanması karmaşık olabilir.
Bu bölümde, görünüm modellerinden model öncelikli görüntüleme gezintisi gerçekleştirmek için kullanılan bir NavigationService
sınıf sunulmuştur. Görünüm modeli sınıflarında gezinti mantığı yerleştirmek, mantığın otomatikleştirilmiş testler aracılığıyla kullanılabilmesi anlamına gelir. Ayrıca görünüm modeli, belirli iş kurallarının uygulandığından emin olmak için gezintiyi denetlemek için mantık uygulayabilir.