Aracılığıyla paylaş


Bölüm 5. Veri Bağlamaları - MVVM

Model-View-ViewModel (MVVM) mimari deseni XAML düşünülerek icat edilmiştir. Desen üç yazılım katmanı arasında ayrım uygular: Görünüm olarak adlandırılan XAML kullanıcı arabirimi; Model olarak adlandırılan temel alınan veriler; ve Görünüm ile Model arasında ViewModel adlı bir aracı. View ve ViewModel genellikle XAML dosyasında tanımlanan veri bağlamaları aracılığıyla bağlanır. Görünüm için BindingContext genellikle ViewModel'in bir örneğidir.

Basit Bir ViewModel

ViewModels'e giriş olarak, ilk olarak bir program olmadan bir programa göz atalım. Daha önce, bir XAML dosyasının diğer derlemelerdeki sınıflara başvurmasına izin vermek için yeni bir XML ad alanı bildirimi tanımlamayı gördünüz. Ad alanı için xml ad alanı bildirimini tanımlayan bir program aşağıdadır System :

xmlns:sys="clr-namespace:System;assembly=netstandard"

Program, statik DateTime.Now özelliğinden geçerli tarih ve saati almak ve bu DateTime değeri üzerinde StackLayoutolarak ayarlamak için BindingContext kullanabilirx:Static:

<StackLayout BindingContext="{x:Static sys:DateTime.Now}" …>

BindingContext özel bir özelliktir: öğesini ayarladığınızda BindingContext , bu öğenin tüm alt öğeleri tarafından devralınır. Bu, öğesinin tüm alt öğelerinin StackLayout aynı BindingContextolduğu ve bu nesnenin özelliklerine yönelik basit bağlamalar içerebileceği anlamına gelir.

One-Shot DateTime programında, alt öğelerden ikisi bu DateTime değerin özelliklerine bağlamalar içerir, ancak diğer iki alt öğe bağlama yolu eksik gibi görünen bağlamalar içerir. Bu, değerin DateTime kendisi için StringFormatkullanıldığı anlamına gelir:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:sys="clr-namespace:System;assembly=netstandard"
             x:Class="XamlSamples.OneShotDateTimePage"
             Title="One-Shot DateTime Page">

    <StackLayout BindingContext="{x:Static sys:DateTime.Now}"
                 HorizontalOptions="Center"
                 VerticalOptions="Center">

        <Label Text="{Binding Year, StringFormat='The year is {0}'}" />
        <Label Text="{Binding StringFormat='The month is {0:MMMM}'}" />
        <Label Text="{Binding Day, StringFormat='The day is {0}'}" />
        <Label Text="{Binding StringFormat='The time is {0:T}'}" />

    </StackLayout>
</ContentPage>

Sorun, sayfa ilk oluşturulduğunda tarih ve saatin bir kez ayarlanması ve hiçbir zaman değişmemiş olmasıdır:

Tarih ve Saati Görüntüleme

XAML dosyası her zaman geçerli saati gösteren bir saat görüntüleyebilir, ancak yardımcı olması için koda ihtiyacı vardır. MVVM açısından düşünürken Model ve ViewModel tamamen kodla yazılmış sınıflardır. Görünüm genellikle veri bağlamaları aracılığıyla ViewModel'de tanımlanan özelliklere başvuran bir XAML dosyasıdır.

Düzgün bir Model ViewModel'i bilmez ve uygun bir ViewModel de Görünüm'ü bilmez. Ancak, bir programcı genellikle ViewModel tarafından kullanıma sunulan veri türlerini belirli kullanıcı arabirimleriyle ilişkili veri türlerine göre uyarlar. Örneğin, model 8 bit karakterli ASCII dizeleri içeren bir veritabanına erişiyorsa, ViewModel'in kullanıcı arabiriminde Özel Unicode kullanımına uyum sağlamak için bu dizeler arasında Unicode dizelerine dönüştürmesi gerekir.

MVVM'nin basit örneklerinde (burada gösterilenler gibi), genellikle Model yoktur ve desen yalnızca veri bağlamalarıyla bağlantılı bir View ve ViewModel içerir.

Bu özelliği her saniye güncelleştiren DateTime adlı DateTimetek bir özelliğe sahip saat için bir ViewModel aşağıda verilmiştir:

using System;
using System.ComponentModel;
using Xamarin.Forms;

namespace XamlSamples
{
    class ClockViewModel : INotifyPropertyChanged
    {
        DateTime dateTime;

        public event PropertyChangedEventHandler PropertyChanged;

        public ClockViewModel()
        {
            this.DateTime = DateTime.Now;

            Device.StartTimer(TimeSpan.FromSeconds(1), () =>
                {
                    this.DateTime = DateTime.Now;
                    return true;
                });
        }

        public DateTime DateTime
        {
            set
            {
                if (dateTime != value)
                {
                    dateTime = value;

                    if (PropertyChanged != null)
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs("DateTime"));
                    }
                }
            }
            get
            {
                return dateTime;
            }
        }
    }
}

ViewModel'ler genellikle arabirimini INotifyPropertyChanged uygular; bu da sınıfının özelliklerinden biri değiştiğinde bir PropertyChanged olay tetiklediği anlamına gelir. içindeki veri bağlama mekanizması, bir özellik değiştiğinde Xamarin.Forms bildirim almak ve hedefi yeni değerle güncel tutmak için bu PropertyChanged olaya bir işleyici ekler.

Bu ViewModel'i temel alan bir saat aşağıdaki kadar basit olabilir:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:XamlSamples;assembly=XamlSamples"
             x:Class="XamlSamples.ClockPage"
             Title="Clock Page">

    <Label Text="{Binding DateTime, StringFormat='{0:T}'}"
           FontSize="Large"
           HorizontalOptions="Center"
           VerticalOptions="Center">
        <Label.BindingContext>
            <local:ClockViewModel />
        </Label.BindingContext>
    </Label>
</ContentPage>

öğesinin ClockViewModel using özellik öğesi etiketlerinin değerine nasıl ayarlandığına BindingContextLabel dikkat edin. Alternatif olarak, bir koleksiyonda örneğini ClockViewModel oluşturabilir ve bir StaticResource işaretleme uzantısı aracılığıyla değerine ayarlayabilirsinizBindingContext.Resources Veya arka planda kod dosyası ViewModel örneğini oluşturabilir.

Binding özelliğindeki TextLabel işaretleme uzantısı özelliği biçimlendirmektedirDateTime. Ekran şu şekildedir:

ViewModel aracılığıyla Tarih ve Saat Görüntülemeyi Görüntüle

Özellikleri noktalarla ayırarak ViewModel özelliğinin tek tek DateTime özelliklerine de erişmek mümkündür:

<Label Text="{Binding DateTime.Second, StringFormat='{0}'}" … >

Etkileşimli MVVM

MVVM genellikle temel alınan veri modelini temel alan etkileşimli bir görünüm için iki yönlü veri bağlamalarıyla birlikte kullanılır.

Burada, bir değeri , Saturationve Luminosity değerlerine Huedönüştüren adlı HslViewModel bir Color sınıf verilmiştir ve bunun tersi de geçerlidir:

using System;
using System.ComponentModel;
using Xamarin.Forms;

namespace XamlSamples
{
    public class HslViewModel : INotifyPropertyChanged
    {
        double hue, saturation, luminosity;
        Color color;

        public event PropertyChangedEventHandler PropertyChanged;

        public double Hue
        {
            set
            {
                if (hue != value)
                {
                    hue = value;
                    OnPropertyChanged("Hue");
                    SetNewColor();
                }
            }
            get
            {
                return hue;
            }
        }

        public double Saturation
        {
            set
            {
                if (saturation != value)
                {
                    saturation = value;
                    OnPropertyChanged("Saturation");
                    SetNewColor();
                }
            }
            get
            {
                return saturation;
            }
        }

        public double Luminosity
        {
            set
            {
                if (luminosity != value)
                {
                    luminosity = value;
                    OnPropertyChanged("Luminosity");
                    SetNewColor();
                }
            }
            get
            {
                return luminosity;
            }
        }

        public Color Color
        {
            set
            {
                if (color != value)
                {
                    color = value;
                    OnPropertyChanged("Color");

                    Hue = value.Hue;
                    Saturation = value.Saturation;
                    Luminosity = value.Luminosity;
                }
            }
            get
            {
                return color;
            }
        }

        void SetNewColor()
        {
            Color = Color.FromHsla(Hue, Saturation, Luminosity);
        }

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

, Saturationve özelliklerinde yapılan değişiklikler özelliğin HueColor değişmesine, değişiklikleri Color ise diğer üç özelliğin değişmesine neden Luminosity olur. Bu, özelliği değişmediği sürece sınıfın olayı çağırmaması PropertyChanged dışında sonsuz bir döngü gibi görünebilir. Bu, aksi takdirde kontrol edilemeyen geri bildirim döngüsüne son verir.

Aşağıdaki XAML dosyası, özelliği ViewModel'in özelliğine Color bağlı olan Color bir BoxView ve , Saturationve özelliklerine Huebağlı üç Slider ve Luminosity üç Label görünümü içerir:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:XamlSamples;assembly=XamlSamples"
             x:Class="XamlSamples.HslColorScrollPage"
             Title="HSL Color Scroll Page">
    <ContentPage.BindingContext>
        <local:HslViewModel Color="Aqua" />
    </ContentPage.BindingContext>

    <StackLayout Padding="10, 0">
        <BoxView Color="{Binding Color}"
                 VerticalOptions="FillAndExpand" />

        <Label Text="{Binding Hue, StringFormat='Hue = {0:F2}'}"
               HorizontalOptions="Center" />

        <Slider Value="{Binding Hue, Mode=TwoWay}" />

        <Label Text="{Binding Saturation, StringFormat='Saturation = {0:F2}'}"
               HorizontalOptions="Center" />

        <Slider Value="{Binding Saturation, Mode=TwoWay}" />

        <Label Text="{Binding Luminosity, StringFormat='Luminosity = {0:F2}'}"
               HorizontalOptions="Center" />

        <Slider Value="{Binding Luminosity, Mode=TwoWay}" />
    </StackLayout>
</ContentPage>

Her Label bir üzerindeki bağlama varsayılandır OneWay. Yalnızca değeri görüntülemesi gerekir. Ancak her Slider birinin bağlaması şeklindedir TwoWay. Bu, öğesinin Slider ViewModel'den başlatılmasını sağlar. Özelliğin Color ViewModel örneği oluşturulurken olarak ayarlandığına Aqua dikkat edin. Ancak içindeki bir değişikliğin Slider ViewModel'de özelliği için yeni bir değer ayarlaması gerekir ve bu da yeni bir renk hesaplar.

İki Yönlü Veri Bağlamaları Kullanan MVVM

ViewModels ile komut oluşturma

Çoğu durumda, MVVM deseni veri öğelerinin işlemesi ile sınırlıdır: ViewModel'deki Paralel veri nesnelerini görüntüle'deki kullanıcı arabirimi nesneleri.

Ancak, bazen Görünüm'de ViewModel'de çeşitli eylemleri tetikleyen düğmeler olması gerekir. Ancak ViewModel, viewmodel'i belirli bir kullanıcı arabirimi paradigmasıyla ilişkilendireceğinden düğmeler için işleyiciler içermemelidir Clicked .

ViewModel'lerin belirli kullanıcı arabirimi nesnelerinden daha bağımsız olmasına ancak yine de ViewModel içinde yöntemlerin çağrılmasına izin vermek için bir komut arabirimi vardır. Bu komut arabirimi, içindeki Xamarin.Formsaşağıdaki öğeler tarafından desteklenir:

  • Button
  • MenuItem
  • ToolbarItem
  • SearchBar
  • TextCell (ve bu nedenle de ImageCell)
  • ListView
  • TapGestureRecognizer

ve ListView öğesi dışındaSearchBar, bu öğeler iki özellik tanımlar:

  • Command türü System.Windows.Input.ICommand
  • CommandParameter türü Object

SearchBar türündeki ICommandbir RefreshCommand özelliği tanımlarken ListViewSearchCommand ve SearchCommandParameter özelliklerini tanımlar.

ICommand Arabirimi iki yöntem ve bir olay tanımlar:

  • void Execute(object arg)
  • bool CanExecute(object arg)
  • event EventHandler CanExecuteChanged

ViewModel türündeki ICommandözellikleri tanımlayabilir. Daha sonra bu özellikleri her Button birinin veya başka bir öğenin özelliğine Command ya da bu arabirimi uygulayan özel bir görünüme bağlayabilirsiniz. İsteğe bağlı olarak, bu ViewModel özelliğine bağlı nesneleri Button (veya diğer öğeleri) tanımlamak için özelliğini ayarlayabilirsinizCommandParameter. dahili olarak, Button kullanıcı öğesine dokunduğunda Buttonyöntemini çağırır Execute ve yöntemine Execute iletirCommandParameter.

Yöntem CanExecute ve CanExecuteChanged olay, bir Button dokunmanın şu anda geçersiz olabileceği durumlarda kullanılır ve bu durumda Button kendisi devre dışı bırakılmalıdır. Button özelliği ilk ayarlandığında ve CanExecuteChanged olay tetiklendiğinde çağrılar CanExecuteCommand. döndürürsefalseCanExecute, Button kendisini devre dışı bırakır ve çağrı oluşturmazExecute.

ViewModel'lerinize komut ekleme konusunda yardım almak için, Xamarin.Forms öğesini uygulayan ICommandiki sınıf tanımlar ve Command<T> burada T ve CanExecutebağımsız değişkenlerinin Execute türüdürCommand. Bu iki sınıf, birkaç oluşturucunun yanı sıra ViewModel'in nesneyi olayı tetiklemeye CanExecuteChanged zorlamak Command için çağırabileceği bir ChangeCanExecute yöntem tanımlar.

Burada, telefon numaralarını girmeye yönelik basit bir tuş takımına yönelik bir ViewModel bulunur. ve CanExecute yönteminin Execute doğrudan oluşturucuda lambda işlevleri olarak tanımlandığına dikkat edin:

using System;
using System.ComponentModel;
using System.Windows.Input;
using Xamarin.Forms;

namespace XamlSamples
{
    class KeypadViewModel : INotifyPropertyChanged
    {
        string inputString = "";
        string displayText = "";
        char[] specialChars = { '*', '#' };

        public event PropertyChangedEventHandler PropertyChanged;

        // Constructor
        public KeypadViewModel()
        {
            AddCharCommand = new Command<string>((key) =>
                {
                    // Add the key to the input string.
                    InputString += key;
                });

            DeleteCharCommand = new Command(() =>
                {
                    // Strip a character from the input string.
                    InputString = InputString.Substring(0, InputString.Length - 1);
                },
                () =>
                {
                    // Return true if there's something to delete.
                    return InputString.Length > 0;
                });
        }

        // Public properties
        public string InputString
        {
            protected set
            {
                if (inputString != value)
                {
                    inputString = value;
                    OnPropertyChanged("InputString");
                    DisplayText = FormatText(inputString);

                    // Perhaps the delete button must be enabled/disabled.
                    ((Command)DeleteCharCommand).ChangeCanExecute();
                }
            }

            get { return inputString; }
        }

        public string DisplayText
        {
            protected set
            {
                if (displayText != value)
                {
                    displayText = value;
                    OnPropertyChanged("DisplayText");
                }
            }
            get { return displayText; }
        }

        // ICommand implementations
        public ICommand AddCharCommand { protected set; get; }

        public ICommand DeleteCharCommand { protected set; get; }

        string FormatText(string str)
        {
            bool hasNonNumbers = str.IndexOfAny(specialChars) != -1;
            string formatted = str;

            if (hasNonNumbers || str.Length < 4 || str.Length > 10)
            {
            }
            else if (str.Length < 8)
            {
                formatted = String.Format("{0}-{1}",
                                          str.Substring(0, 3),
                                          str.Substring(3));
            }
            else
            {
                formatted = String.Format("({0}) {1}-{2}",
                                          str.Substring(0, 3),
                                          str.Substring(3, 3),
                                          str.Substring(6));
            }
            return formatted;
        }

        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Bu ViewModel, özelliğinin AddCharCommand her biri tarafından tanımlanan birkaç düğmenin (veya komut arabirimi olan başka bir şeyin) özelliğine CommandParameterbağlı Command olduğunu varsayar. Bu düğmeler bir özelliğe karakter InputString ekler ve bu da özellik için DisplayText telefon numarası olarak biçimlendirilir.

ayrıca adlı DeleteCharCommandtürünün ICommand ikinci bir özelliği de vardır. Bu, bir geri aralığı düğmesine bağlıdır, ancak silinecek karakter yoksa düğme devre dışı bırakılmalıdır.

Aşağıdaki tuş takımı görsel olarak olabildiğince karmaşık değildir. Bunun yerine, komut arabiriminin kullanımını daha net bir şekilde göstermek için işaretleme en aza indirilmiştir:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:XamlSamples;assembly=XamlSamples"
             x:Class="XamlSamples.KeypadPage"
             Title="Keypad Page">

    <Grid HorizontalOptions="Center"
          VerticalOptions="Center">
        <Grid.BindingContext>
            <local:KeypadViewModel />
        </Grid.BindingContext>

        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="80" />
            <ColumnDefinition Width="80" />
            <ColumnDefinition Width="80" />
        </Grid.ColumnDefinitions>

        <!-- Internal Grid for top row of items -->
        <Grid Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>

            <Frame Grid.Column="0"
                   OutlineColor="Accent">
                <Label Text="{Binding DisplayText}" />
            </Frame>

            <Button Text="&#x21E6;"
                    Command="{Binding DeleteCharCommand}"
                    Grid.Column="1"
                    BorderWidth="0" />
        </Grid>

        <Button Text="1"
                Command="{Binding AddCharCommand}"
                CommandParameter="1"
                Grid.Row="1" Grid.Column="0" />

        <Button Text="2"
                Command="{Binding AddCharCommand}"
                CommandParameter="2"
                Grid.Row="1" Grid.Column="1" />

        <Button Text="3"
                Command="{Binding AddCharCommand}"
                CommandParameter="3"
                Grid.Row="1" Grid.Column="2" />

        <Button Text="4"
                Command="{Binding AddCharCommand}"
                CommandParameter="4"
                Grid.Row="2" Grid.Column="0" />

        <Button Text="5"
                Command="{Binding AddCharCommand}"
                CommandParameter="5"
                Grid.Row="2" Grid.Column="1" />

        <Button Text="6"
                Command="{Binding AddCharCommand}"
                CommandParameter="6"
                Grid.Row="2" Grid.Column="2" />

        <Button Text="7"
                Command="{Binding AddCharCommand}"
                CommandParameter="7"
                Grid.Row="3" Grid.Column="0" />

        <Button Text="8"
                Command="{Binding AddCharCommand}"
                CommandParameter="8"
                Grid.Row="3" Grid.Column="1" />

        <Button Text="9"
                Command="{Binding AddCharCommand}"
                CommandParameter="9"
                Grid.Row="3" Grid.Column="2" />

        <Button Text="*"
                Command="{Binding AddCharCommand}"
                CommandParameter="*"
                Grid.Row="4" Grid.Column="0" />

        <Button Text="0"
                Command="{Binding AddCharCommand}"
                CommandParameter="0"
                Grid.Row="4" Grid.Column="1" />

        <Button Text="#"
                Command="{Binding AddCharCommand}"
                CommandParameter="#"
                Grid.Row="4" Grid.Column="2" />
    </Grid>
</ContentPage>

Command Bu işaretlemede görüntülenen ilk Button öğesinin özelliği öğesine bağlıdırDeleteCharCommand; geri kalanıAddCharCommand, yüzde görünen Button karakterle aynı olan ile CommandParameter ilişkilidir. İşte program şu şekildedir:

MVVM ve Komutları kullanarak hesap makinesi

Zaman Uyumsuz Yöntemleri Çağırma

Komutlar zaman uyumsuz yöntemleri de çağırabilir. Bu, yöntemini belirtirken ve await anahtar sözcükleri kullanılarak async elde edilirExecute:

DownloadCommand = new Command (async () => await DownloadAsync ());

Bu, yönteminin DownloadAsync bir Task olduğunu ve beklenmesi gerektiğini gösterir:

async Task DownloadAsync ()
{
    await Task.Run (() => Download ());
}

void Download ()
{
    ...
}

Gezinti Menüsü Uygulama

Bu makale serisindeki tüm kaynak kodunu içeren örnek program, giriş sayfası için bir ViewModel kullanır. Bu ViewModel, adlı TypeTitleüç özelliğe sahip ve Description örnek sayfaların her birinin türünü, bir başlığı ve kısa bir açıklamayı içeren kısa bir sınıfın tanımıdır. Ayrıca ViewModel, programdaki tüm sayfaların koleksiyonu olan adlı All statik özelliği tanımlar:

public class PageDataViewModel
{
    public PageDataViewModel(Type type, string title, string description)
    {
        Type = type;
        Title = title;
        Description = description;
    }

    public Type Type { private set; get; }

    public string Title { private set; get; }

    public string Description { private set; get; }

    static PageDataViewModel()
    {
        All = new List<PageDataViewModel>
        {
            // Part 1. Getting Started with XAML
            new PageDataViewModel(typeof(HelloXamlPage), "Hello, XAML",
                                  "Display a Label with many properties set"),

            new PageDataViewModel(typeof(XamlPlusCodePage), "XAML + Code",
                                  "Interact with a Slider and Button"),

            // Part 2. Essential XAML Syntax
            new PageDataViewModel(typeof(GridDemoPage), "Grid Demo",
                                  "Explore XAML syntax with the Grid"),

            new PageDataViewModel(typeof(AbsoluteDemoPage), "Absolute Demo",
                                  "Explore XAML syntax with AbsoluteLayout"),

            // Part 3. XAML Markup Extensions
            new PageDataViewModel(typeof(SharedResourcesPage), "Shared Resources",
                                  "Using resource dictionaries to share resources"),

            new PageDataViewModel(typeof(StaticConstantsPage), "Static Constants",
                                  "Using the x:Static markup extensions"),

            new PageDataViewModel(typeof(RelativeLayoutPage), "Relative Layout",
                                  "Explore XAML markup extensions"),

            // Part 4. Data Binding Basics
            new PageDataViewModel(typeof(SliderBindingsPage), "Slider Bindings",
                                  "Bind properties of two views on the page"),

            new PageDataViewModel(typeof(SliderTransformsPage), "Slider Transforms",
                                  "Use Sliders with reverse bindings"),

            new PageDataViewModel(typeof(ListViewDemoPage), "ListView Demo",
                                  "Use a ListView with data bindings"),

            // Part 5. From Data Bindings to MVVM
            new PageDataViewModel(typeof(OneShotDateTimePage), "One-Shot DateTime",
                                  "Obtain the current DateTime and display it"),

            new PageDataViewModel(typeof(ClockPage), "Clock",
                                  "Dynamically display the current time"),

            new PageDataViewModel(typeof(HslColorScrollPage), "HSL Color Scroll",
                                  "Use a view model to select HSL colors"),

            new PageDataViewModel(typeof(KeypadPage), "Keypad",
                                  "Use a view model for numeric keypad logic")
        };
    }

    public static IList<PageDataViewModel> All { private set; get; }
}

için MainPage XAML dosyası, özelliği bu All özelliğe ayarlanmış olan ve her sayfanın ve Description özelliklerini görüntülemek Title için bir içeren bir TextCell öğesini tanımlar ListBoxItemsSource:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:XamlSamples"
             x:Class="XamlSamples.MainPage"
             Padding="5, 0"
             Title="XAML Samples">

    <ListView ItemsSource="{x:Static local:PageDataViewModel.All}"
              ItemSelected="OnListViewItemSelected">
        <ListView.ItemTemplate>
            <DataTemplate>
                <TextCell Text="{Binding Title}"
                          Detail="{Binding Description}" />
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</ContentPage>

Sayfalar kaydırılabilir bir listede gösterilir:

Kaydırılabilir sayfa listesi

Kullanıcı bir öğe seçtiğinde arka planda kod dosyasındaki işleyici tetikleniyor. İşleyici, back null özelliğini ListBox olarak ayarlar SelectedItem ve ardından seçili sayfayı örnekleyip bu sayfaya gider:

private async void OnListViewItemSelected(object sender, SelectedItemChangedEventArgs args)
{
    (sender as ListView).SelectedItem = null;

    if (args.SelectedItem != null)
    {
        PageDataViewModel pageData = args.SelectedItem as PageDataViewModel;
        Page page = (Page)Activator.CreateInstance(pageData.Type);
        await Navigation.PushAsync(page);
    }
}

Video

Xamarin Evolve 2016: MVVM Made Simple with Xamarin.Forms and Prism

Özet

XAML, özellikle veri bağlama ve MVVM kullanıldığında uygulamalarda kullanıcı arabirimlerini Xamarin.Forms tanımlamaya yönelik güçlü bir araçtır. Sonuç, kodda tüm arka plan desteğine sahip bir kullanıcı arabiriminin temiz, zarif ve potansiyel olarak araçlanabilir bir gösterimidir.

Channel 9 ve YouTube'da daha fazla Xamarin videosu bulun.