Aracılığıyla paylaş


Ayrıntılı veri bağlama

Önemli API'ler

Uyarı

Bu konu başlığında veri bağlama özellikleri ayrıntılı olarak açıklanmaktadır. Kısa ve pratik bir giriş için bkz. Veri bağlamaya genel bakış.

Bu konu, Windows.UI.Xaml.Data ad alanında bulunan API'ler için veri bağlama hakkındadır.

Veri bağlama, uygulamanızın kullanıcı arabiriminin verileri görüntülemesine ve isteğe bağlı olarak bu verilerle eşitlenmiş durumda kalmasına yönelik bir yoldur. Veri bağlama, veri endişesini kullanıcı arabiriminden ayırmanıza olanak tanır ve bu da daha basit bir kavramsal modelin yanı sıra uygulamanızın daha iyi okunabilirliği, test edilebilirliği ve sürdürülebilirliğiyle sonuçlanabilir.

Veri bağlamayı, kullanıcı arabirimi ilk kez gösterildiğinde bir veri kaynağındaki değerleri görüntülemek için kullanabilirsiniz, ancak bu değerlerdeki değişikliklere yanıt vermek için kullanamazsınız. Bu, tek seferlik olarak adlandırılan bir bağlama modudur ve çalışma zamanı sırasında değişmeyen bir değer için iyi çalışır. Alternatif olarak, değerleri "gözlemlemeyi" ve değiştiğinde kullanıcı arabirimini güncelleştirmeyi seçebilirsiniz. Bu mod tek yönlü olarak adlandırılır ve salt okunur veriler için iyi çalışır. Sonuç olarak, kullanıcının kullanıcı arabirimindeki değerlerde yaptığı değişikliklerin otomatik olarak veri kaynağına geri gönderilmesi için hem gözlemlemeyi hem de güncelleştirmeyi seçebilirsiniz. Bu mod iki yönlü olarak adlandırılır ve okuma-yazma verileri için iyi çalışır. Aşağıda bazı örnekler verilmiştir.

  • Resmi geçerli kullanıcının fotoğrafına bağlamak için tek seferlik modu kullanabilirsiniz.
  • ListView'ı gazete bölümüne göre gruplandırılmış gerçek zamanlı haber makalelerinden oluşan bir koleksiyona bağlamak için tek yönlü modu kullanabilirsiniz.
  • TextBox'ı bir formdaki müşterinin adına bağlamak için iki yönlü modu kullanabilirsiniz.

Moddan bağımsız olarak iki bağlama türü vardır ve her ikisi de genellikle kullanıcı arabirimi işaretlemesinde bildirilir. {x:Bind} işaretleme uzantısını veya {Binding} işaretleme uzantısını kullanmayı seçebilirsiniz. Ayrıca, aynı kullanıcı arabirimi öğesinde bile aynı uygulamada ikisinin bir karışımını kullanabilirsiniz. {x:Bind} Windows 10 için yeni ve daha iyi performansa sahip. Bu konuda açıklanan tüm ayrıntılar, açıkça aksini söylemediğimiz sürece her iki bağlama türü için de geçerlidir.

{x:Bind} gösteren örnek uygulamalar

{Binding} gösteren örnek uygulamalar

Her bağlama bu parçaları içerir

  • Bağlama kaynağı. Bu, bağlama verilerinin kaynağıdır ve kullanıcı arabiriminizde değerlerini görüntülemek istediğiniz üyeleri olan herhangi bir sınıfın örneği olabilir.
  • Bağlama hedefi. Bu, verileri görüntüleyen kullanıcı arabiriminizdeki FrameworkElement'in DependencyProperty özelliğidir.
  • Bağlama nesnesi. Bu, veri değerlerini kaynaktan hedefe ve isteğe bağlı olarak hedeften kaynağa aktaran parçadır. Bağlama nesnesi XAML yükleme zamanında {x:Bind} veya {Binding} işaretleme uzantınızdan oluşturulur.

Aşağıdaki bölümlerde bağlama kaynağını, bağlama hedefini ve bağlama nesnesini daha yakından inceleyeceğiz. Bölümleri, düğmenin içeriğini HostViewModel adlı bir sınıfa ait olan NextButtonText adlı dize özelliğine bağlama örneğiyle birleştireceğiz.

Bağlama kaynağı

Burada bağlama kaynağı olarak kullanabileceğimiz bir sınıfın çok basit bir uygulaması yer alır.

C++/WinRT kullanıyorsanız, aşağıdaki C++/WinRT kod örneği listesinde gösterildiği gibi adlı yeni Midl Dosyası (.idl) öğelerini projeye ekleyin. Bu yeni dosyaların içeriğini listede gösterilen MIDL 3.0 koduyla değiştirin, ve .cppoluşturmak HostViewModel.h için projeyi derleyin ve ardından listeyle eşleşecek şekilde oluşturulan dosyalara kod ekleyin. Oluşturulan dosyalar ve bunları projenize kopyalama hakkında daha fazla bilgi için bkz. XAML denetimleri; C++/WinRT özelliğine bağlama.

public class HostViewModel
{
    public HostViewModel()
    {
        this.NextButtonText = "Next";
    }

    public string NextButtonText { get; set; }
}
// HostViewModel.idl
namespace DataBindingInDepth
{
    runtimeclass HostViewModel
    {
        HostViewModel();
        String NextButtonText;
    }
}

// HostViewModel.h
// Implement the constructor like this, and add this field:
...
HostViewModel() : m_nextButtonText{ L"Next" } {}
...
private:
    std::wstring m_nextButtonText;
...

// HostViewModel.cpp
// Implement like this:
...
hstring HostViewModel::NextButtonText()
{
    return hstring{ m_nextButtonText };
}

void HostViewModel::NextButtonText(hstring const& value)
{
    m_nextButtonText = value;
}
...

Bu HostViewModel uygulaması ve NextButtonText özelliği yalnızca bir kerelik bağlama için uygundur. Ancak tek yönlü ve iki yönlü bağlamalar son derece yaygındır ve bu bağlama türlerinde bağlama kaynağının veri değerlerindeki değişikliklere yanıt olarak kullanıcı arabirimi otomatik olarak güncelleştirilir. Bu bağlama türlerinin doğru çalışması için bağlama kaynağınızı bağlama nesnesine "gözlemlenebilir" hale getirmeniz gerekir. Bu nedenle örneğimizde , NextButtonText özelliğine tek yönlü veya iki yönlü bağlama yapmak istiyorsak, çalışma zamanında bu özelliğin değerine yapılan tüm değişikliklerin bağlama nesnesine gözlemlenebilir hale getirilmesi gerekir.

Bunu yapmanın bir yolu, dependencyObject'ten bağlama kaynağınızı temsil eden sınıfı türetmek ve dependencyProperty aracılığıyla bir veri değeri ortaya çıkarmaktır. FrameworkElement bu şekilde gözlemlenebilir hale gelir. FrameworkElements , hemen kullanıma hazır iyi bağlama kaynaklarıdır.

Sınıfı gözlemlenebilir hale getirmenin daha basit bir yolu ve zaten bir temel sınıfı olan sınıflar için gerekli olan, System.ComponentModel.INotifyPropertyChanged uygulamaktır. Bu yalnızca PropertyChanged adlı tek bir olay uygulamayı içerir. HostViewModel kullanan bir örnek aşağıda verilmiştir.

...
using System.ComponentModel;
using System.Runtime.CompilerServices;
...
public class HostViewModel : INotifyPropertyChanged
{
    private string nextButtonText;

    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    public HostViewModel()
    {
        this.NextButtonText = "Next";
    }

    public string NextButtonText
    {
        get { return this.nextButtonText; }
        set
        {
            this.nextButtonText = value;
            this.OnPropertyChanged();
        }
    }

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        // Raise the PropertyChanged event, passing the name of the property whose value has changed.
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
// HostViewModel.idl
namespace DataBindingInDepth
{
    runtimeclass HostViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
    {
        HostViewModel();
        String NextButtonText;
    }
}

// HostViewModel.h
// Add this field:
...
    winrt::event_token PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler);
    void PropertyChanged(winrt::event_token const& token) noexcept;

private:
    winrt::event<Windows::UI::Xaml::Data::PropertyChangedEventHandler> m_propertyChanged;
...

// HostViewModel.cpp
// Implement like this:
...
void HostViewModel::NextButtonText(hstring const& value)
{
    if (m_nextButtonText != value)
    {
        m_nextButtonText = value;
        m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"NextButtonText" });
    }
}

winrt::event_token HostViewModel::PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
{
    return m_propertyChanged.add(handler);
}

void HostViewModel::PropertyChanged(winrt::event_token const& token) noexcept
{
    m_propertyChanged.remove(token);
}
...

Artık NextButtonText özelliği gözlemlenebilir. Bu özelliğe tek yönlü veya iki yönlü bağlama yazdığınızda (daha sonra göstereceğiz), sonuçta elde edilen bağlama nesnesi PropertyChanged olayına abone olur. Bu olay tetiklendiğinde, bağlama nesnesinin işleyicisi değiştirilen özelliğin adını içeren bir bağımsız değişken alır. Bağlama nesnesi, hangi özelliğin değerinin gidip yeniden okunduğunu bu şekilde anlar.

Yukarıda gösterilen deseni birden çok kez uygulamanız gerekmemesi için, C# kullanıyorsanız QuizGame örneğinde ("Ortak" klasörde) bulabileceğiniz BindableBase temel sınıfından türetebilirsiniz. Bunun nasıl göründüğüne dair bir örnek aşağıda verilmiştır.

public class HostViewModel : BindableBase
{
    private string nextButtonText;

    public HostViewModel()
    {
        this.NextButtonText = "Next";
    }

    public string NextButtonText
    {
        get { return this.nextButtonText; }
        set { this.SetProperty(ref this.nextButtonText, value); }
    }
}
// Your BindableBase base class should itself derive from Windows::UI::Xaml::DependencyObject. Then, in HostViewModel.idl, derive from BindableBase instead of implementing INotifyPropertyChanged.

Uyarı

C++/WinRT için, uygulamanızda bir temel sınıftan türetilen herhangi bir çalışma zamanı sınıfı , birleştirilebilir sınıf olarak bilinir. Ve birleştirilebilir sınıflar ile ilgili kısıtlamalar vardır. Bir uygulamanın, Visual Studio ve Microsoft Store tarafından gönderileri doğrulamak için kullanılan Windows Uygulama Sertifikasyon Seti testlerini geçirmesi için (ve bu nedenle uygulamanın Microsoft Store'a başarıyla alınması için), bir oluşturulabilir sınıfın sonuçta bir Windows temel sınıfından türetilmesi gerekir. Yani devralma hiyerarşisinin kökündeki sınıfın Windows.* ad alanından kaynaklanan bir tür olması gerekir. Temel sınıftan bir çalışma zamanı sınıfı türetmeye ihtiyacınız varsa (örneğin, tüm görünüm modellerinizin türetebileceği bir BindableBase sınıfı uygulamak için), Windows.UI.Xaml.DependencyObject'ten türetebilirsiniz.

PropertyChanged olayını String.Empty veya null bağımsız değişkeniyle yükseltmek, nesnedeki dizin oluşturucu olmayan tüm özelliklerin yeniden okunması gerektiğini gösterir. Belirli dizin oluşturucular için "Item[indexer]" bağımsız değişkenini (dizin oluşturucunun dizin değeri olduğu) veya tüm dizin oluşturucular için "Öğe[]" değerini kullanarak nesnedeki dizin oluşturucu özelliklerinin değiştiğini belirtmek için olayı tetikleyebilirsiniz.

Bağlama kaynağı, özellikleri veri içeren tek bir nesne olarak veya nesne koleksiyonu olarak işlenebilir. C# ve Visual Basic kodunda, çalışma zamanında değişmeyen bir koleksiyonu görüntülemek için List(Of T) uygulayan bir nesneye tek seferlik bağlanabilirsiniz. Gözlemlenebilir bir koleksiyon için (öğeler koleksiyona eklendiğinde ve koleksiyondan kaldırıldığında gözlemleme), bunun yerine ObservableCollection(Of T) öğesine tek yönlü bağlama. C++/CX kodunda, hem gözlemlenebilir hem de gözlemlenemeyen koleksiyonlar için Vector<T'ye> bağlayabilirsiniz ve C++/WinRT'nin kendi türleri vardır. Kendi koleksiyon sınıflarınıza bağlanmak için aşağıdaki tabloda yer alan yönergeleri kullanın.

Scenario C# ve VB (CLR) C++/WinRT C++/CX
Bir nesneye bağlama. Herhangi bir nesne olabilir. Herhangi bir nesne olabilir. Nesnenin BindableAttribute olması veya ICustomPropertyProvider uygulaması gerekir.
İlişkili bir nesneden özellik değişikliği bildirimleri alma. Nesnenin INotifyPropertyChanged uygulaması gerekir. Nesnenin INotifyPropertyChanged uygulaması gerekir. Nesnenin INotifyPropertyChanged uygulaması gerekir.
Bir koleksiyona bağlama. Liste(T) IInspectable veya IBindableObservableVector'ın IVector'ı. Bkz . XAML öğeleri denetimleri; C++/WinRT koleksiyonuna bağlama ve C++/WinRT ile Koleksiyonlar. Vektör<T>
İlişkili bir koleksiyondan koleksiyon değişikliği bildirimleri alma. ObservableCollection(T) IInspectable'ın IObservableVector'ı. Örneğin , winrt::single_threaded_observable_vector<T>. IObservableVector<T>. Vektör<T> bu arabirimi uygular.
Bağlamayı destekleyen bir koleksiyon uygulayın. Listeyi Genişlet (T) veya IList, IList(Of Object), IEnumerable veya IEnumerable(Of Object) uygulayın. Genel IList(Of T) ve IEnumerable(Of T) bağlama desteklenmez. IInspectable'ınIVector'ını uygulayın. Bkz . XAML öğeleri denetimleri; C++/WinRT koleksiyonuna bağlama ve C++/WinRT ile Koleksiyonlar. IBindableVector, IBindableIterable, IVector<Object^>, IIterable<Object^>, IVector<IInspectable*> veya IIterable<IInspectable*> uygulayın. Genel IVector<T> ve IIterable<T'ye> bağlama desteklenmez.
Koleksiyon değişikliği bildirimlerini destekleyen bir koleksiyon uygulayın. ObservableCollection(Of T) öğesini genişletin veya (genel olmayan) IList ve INotifyCollectionChanged uygulayın. IInspectable veya IBindableObservableVector için IObservableVector uygulayın. IBindableVector ve IBindableObservableVector'ı uygulayın.
Artımlı yüklemeyi destekleyen bir koleksiyon uygulayın. ObservableCollection(Of T) öğesini genişletin veya (genel olmayan) IList ve INotifyCollectionChanged uygulayın. Ayrıca , ISupportIncrementalLoading'i uygulayın. IInspectable veya IBindableObservableVector için IObservableVector uygulayın. Ayrıca, ISupportIncrementalLoading'i uygulayın IBindableVector, IBindableObservableVector ve ISupportIncrementalLoading'i uygulayın.

Artımlı yükleme kullanarak liste denetimlerini rastgele büyük veri kaynaklarına bağlayabilir ve yine de yüksek performans elde edebilirsiniz. Örneğin, tüm sonuçları aynı anda yüklemek zorunda kalmadan liste denetimlerini Bing resim sorgusu sonuçlarına bağlayabilirsiniz. Bunun yerine, yalnızca bazı sonuçları hemen yüklersiniz ve gerektiğinde ek sonuçlar yüklersiniz. Artımlı yüklemeyi desteklemek için, koleksiyon değişikliği bildirimlerini destekleyen bir veri kaynağına ISupportIncrementalLoading uygulamanız gerekir. Veri bağlama altyapısı daha fazla veri istediğinde, veri kaynağınızın uygun istekleri yapması, sonuçları tümleştirmesi ve ardından kullanıcı arabirimini güncelleştirmek için uygun bildirimleri göndermesi gerekir.

Hedef bağlama

Aşağıdaki iki örnekte Button.Content özelliği bağlama hedefidir ve değeri bağlama nesnesini bildiren bir işaretleme uzantısına ayarlanır. İlk {x:Bind} ve ardından {Binding} gösteriliyor. İşaretlemede bağlamaların bildirilmesi yaygın bir durumdur (kullanışlı, okunabilir ve araçlanabilir). Ancak işaretlemeden kaçınabilir ve gerekirse zorunlu olarak (program aracılığıyla) Bağlama sınıfının bir örneğini oluşturabilirsiniz.

<Button Content="{x:Bind ...}" ... />
<Button Content="{Binding ...}" ... />

C++/WinRT veya Visual C++ bileşen uzantıları (C++/CX) kullanıyorsanız, {Binding} işaretleme uzantısını kullanmak istediğiniz herhangi bir çalışma zamanı sınıfına BindableAttribute özniteliğini eklemeniz gerekir.

Önemli

C++/WinRT kullanıyorsanız, Windows SDK 10.0.17763.0 (Windows 10, sürüm 1809) veya sonraki bir sürümünü yüklediyseniz BindableAttribute özniteliği kullanılabilir. Bu öznitelik olmadan, {Binding} işaretleme uzantısını kullanabilmek için ICustomPropertyProvider ve ICustomProperty arabirimlerini uygulamanız gerekir.

{x:Bind} kullanılarak bildirilen bağlama nesnesi

{x:Bind} işaretlememizi yazmadan önce yapmamız gereken bir adım var. Biçimlendirme sayfamızı temsil eden sınıftan bağlama kaynak sınıfımızı kullanıma sunmamız gerekir. Bunu, MainPage sayfa sınıfımıza bir özellik (bu örnekte HostViewModel türünde) ekleyerek yaparız.

namespace DataBindingInDepth
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            this.ViewModel = new HostViewModel();
        }
    
        public HostViewModel ViewModel { get; set; }
    }
}
// MainPage.idl
import "HostViewModel.idl";

namespace DataBindingInDepth
{
    runtimeclass MainPage : Windows.UI.Xaml.Controls.Page
    {
        MainPage();
        HostViewModel ViewModel{ get; };
    }
}

// MainPage.h
// Include a header, and add this field:
...
#include "HostViewModel.h"
...
    DataBindingInDepth::HostViewModel ViewModel();

private:
    DataBindingInDepth::HostViewModel m_viewModel{ nullptr };
...

// MainPage.cpp
// Implement like this:
...
MainPage::MainPage()
{
    InitializeComponent();

}

DataBindingInDepth::HostViewModel MainPage::ViewModel()
{
    return m_viewModel;
}
...

Bu işlem tamamlandı, artık bağlama nesnesini bildiren işaretlemeye daha yakından bakabiliriz. Aşağıdaki örnekte, daha önce "Bağlama hedefi" bölümünde kullandığımız Button.Content bağlama hedefi kullanılmıştır ve HostViewModel.NextButtonText özelliğine bağlı olduğu gösterilmektedir.

<!-- MainPage.xaml -->
<Page x:Class="DataBindingInDepth.Mainpage" ... >
    <Button Content="{x:Bind Path=ViewModel.NextButtonText, Mode=OneWay}" ... />
</Page>

Yol için belirttiğimiz değere dikkat edin. Bu değer sayfanın bağlamında yorumlanır ve bu durumda yol, MainPage sayfasına yeni eklediğimiz ViewModel özelliğine başvurarak başlar. Bu özellik bir HostViewModel örneği döndürür ve böylece HostViewModel.NextButtonText özelliğine erişmek için bu nesnenin içine gidebiliriz. Bir kerelik {x:Bind} varsayılanını geçersiz kılmak için Mode değerini belirtiriz.

Path özelliği iç içe özelliklere, ekli özelliklere ve tamsayı ve dize dizin oluşturucularına bağlama için çeşitli söz dizimi seçeneklerini destekler. Daha fazla bilgi için bkz . Özellik yolu söz dizimi. Dize dizin oluşturucularına bağlama, ICustomPropertyProvider uygulamak zorunda kalmadan dinamik özelliklere bağlamanın etkisini sağlar. Diğer ayarlar için bkz. {x:Bind} işaretleme uzantısı.

HostViewModel.NextButtonText özelliğinin gerçekten gözlemlenebilir olduğunu göstermek için düğmeye bir Click olay işleyicisi ekleyin ve HostViewModel.NextButtonText değerini güncelleştirin. Oluştur, çalıştır ve düğmenin İçerik güncelleştirmesinin değerini görmek için düğmeye tıklayın.

// MainPage.xaml.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
    this.ViewModel.NextButtonText = "Updated Next button text";
}
// MainPage.cpp
void MainPage::ClickHandler(IInspectable const&, RoutedEventArgs const&)
{
    ViewModel().NextButtonText(L"Updated Next button text");
}

Uyarı

TextBox.Text dosyasındaki değişiklikler, TextBox her kullanıcı tuş vuruşu sonrasında değil, odağı kaybettiğinde iki yönlü bağlı kaynağa gönderilir.

DataTemplate ve x:DataType

DataTemplate içinde (öğe şablonu, içerik şablonu veya üst bilgi şablonu olarak kullanılır), Path değeri sayfanın bağlamında değil, şablonlanan veri nesnesi bağlamında yorumlanır. Bağlamalarının derleme zamanında doğrulanabilmesi (ve bunlar için verimli kod oluşturulabilmesi) için veri şablonunda {x:Bind} kullanılırken , DataTemplate'ınx:DataType kullanarak veri nesnesinin türünü bildirmesi gerekir. Aşağıda verilen örnek, SampleDataGroup nesneleri koleksiyonuna bağlı bir öğe denetiminin ItemTemplate değeri olarak kullanılabilir.

<DataTemplate x:Key="SimpleItemTemplate" x:DataType="data:SampleDataGroup">
    <StackPanel Orientation="Vertical" Height="50">
      <TextBlock Text="{x:Bind Title}"/>
      <TextBlock Text="{x:Bind Description}"/>
    </StackPanel>
  </DataTemplate>

Yolunuzdaki zayıf türemiş nesneler

Örneğin, Title adlı bir dize özelliği uygulayan SampleDataGroup adlı bir türe sahip olduğunuzu düşünün. Ayrıca nesne türünde olan ancak aslında SampleDataGroup örneğini döndüren MainPage.SampleDataGroupAsObject özelliğine sahipsiniz. Title özelliği tür nesnesinde bulunamadığından bağlama <TextBlock Text="{x:Bind SampleDataGroupAsObject.Title}"/> derleme hatasına neden olur. Bunun çözümü, Yol söz dizimine şöyle bir atama eklemektir: <TextBlock Text="{x:Bind ((data:SampleDataGroup)SampleDataGroupAsObject).Title}"/>. Burada, Öğenin nesne olarak bildirildiği ancak aslında textBlock olduğu başka bir örnek verilmiştir: <TextBlock Text="{x:Bind Element.Text}"/>. Ve bir döküm sorunu çözer: <TextBlock Text="{x:Bind ((TextBlock)Element).Text}"/>.

Verileriniz zaman uyumsuz olarak yüklenirse

Sayfalarınızın kısmi sınıflarında derleme zamanında {x:Bind} desteğine yönelik kod oluşturulur. Bu dosyalar klasörünüzde obj (C#için) <view name>.g.csgibi adlarla bulunabilir. Oluşturulan kod, sayfanızın Yükleme olayı için bir işleyici içerir ve bu işleyici, sayfanızın bağlamalarını temsil eden oluşturulan bir sınıfta Initialize yöntemini çağırır. Sırayla başlatın , bağlama kaynağı ile hedef arasında veri taşımaya başlamak için Update'i çağırır. Yükleme , sayfanın veya kullanıcı denetiminin ilk ölçü geçişi öncesinde oluşturulur. Dolayısıyla verileriniz zaman uyumsuz olarak yüklenirse Initialize çağrılınca hazır olmayabilir. Bu nedenle, verileri yükledikten sonra çağrısı this.Bindings.Update();yaparak tek seferlik bağlamaların başlatılmasını zorlayabilirsiniz. Zaman uyumsuz olarak yüklenen veriler için yalnızca bir kerelik bağlamalara ihtiyacınız varsa bunları bu şekilde başlatmak, tek yönlü bağlamalara sahip olmak ve değişiklikleri dinlemekten çok daha ucuzdur. Verilerinizde ayrıntılı değişiklikler yapılmazsa ve belirli bir eylemin parçası olarak güncelleştirilme olasılığı varsa, bağlamalarınızı tek seferlik yapabilir ve istediğiniz zaman Güncelleştirme çağrısıyla el ile güncelleştirmeyi zorlayabilirsiniz.

Uyarı

{x:Bind} bir JSON nesnesinin sözlük yapısında gezinme veya ördek yazma gibi geç bağlı senaryolar için uygun değildir. "Ördek yazma", özellik adlarındaki sözcük temelli eşleşmelere göre yazmanın zayıf bir biçimidir ("eğer yürüyorsa, yüzüyorsa ve ördek gibi şarlatansa, o zaman ördektir"). Ördek yazarken Age özelliğine yapılan bağlama, bir Kişi veya Şarap nesnesinden (bu türlerin her birinin bir Age özelliği olduğu varsayılarak) eşit olarak karşılanabilir. Bu senaryolar için {Binding} işaretleme uzantısını kullanın.

{Binding} kullanılarak bildirilen bağlama nesnesi

C++/WinRT veya Visual C++ bileşen uzantıları (C++/CX) kullanıyorsanız , {Binding} işaretleme uzantısını kullanmak için bindableAttribute özniteliğini bağlamak istediğiniz herhangi bir çalışma zamanı sınıfına eklemeniz gerekir. {x:Bind} kullanmak için bu özniteliğe ihtiyacınız yoktur.

// HostViewModel.idl
// Add this attribute:
[Windows.UI.Xaml.Data.Bindable]
runtimeclass HostViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
...

Önemli

C++/WinRT kullanıyorsanız, Windows SDK 10.0.17763.0 (Windows 10, sürüm 1809) veya sonraki bir sürümünü yüklediyseniz BindableAttribute özniteliği kullanılabilir. Bu öznitelik olmadan, {Binding} işaretleme uzantısını kullanabilmek için ICustomPropertyProvider ve ICustomProperty arabirimlerini uygulamanız gerekir.

{Binding} varsayılan olarak işaretleme sayfanızın DataContext'ine bağlandığınızı varsayar. Bu nedenle sayfamızın DataContext değerini bağlama kaynak sınıfımızın (bu örnekte HostViewModel türünde) bir örneği olarak ayarlayacağız. Aşağıdaki örnekte bağlama nesnesini bildiren işaretleme gösterilmektedir. Daha önce "Bağlama hedefi" bölümünde kullandığımız Button.Content bağlama hedefini kullanıyoruz ve HostViewModel.NextButtonText özelliğine bağlanıyoruz.

<Page xmlns:viewmodel="using:DataBindingInDepth" ... >
    <Page.DataContext>
        <viewmodel:HostViewModel x:Name="viewModelInDataContext"/>
    </Page.DataContext>
    ...
    <Button Content="{Binding Path=NextButtonText}" ... />
</Page>
// MainPage.xaml.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
    this.viewModelInDataContext.NextButtonText = "Updated Next button text";
}
// MainPage.cpp
void MainPage::ClickHandler(IInspectable const&, RoutedEventArgs const&)
{
    viewModelInDataContext().NextButtonText(L"Updated Next button text");
}

Yol için belirttiğimiz değere dikkat edin. Bu değer, sayfanın DataContext bağlamında yorumlanır ve bu örnekte HostViewModel örneği olarak ayarlanır. Yol HostViewModel.NextButtonText özelliğine başvurur. Tek yönlü {Binding} varsayılanı burada çalıştığından Modu atlayabiliriz.

Kullanıcı arabirimi öğesi için Varsayılan DataContext değeri, üst öğesinin devralınan değeridir. Tabii ki DataContext'i açıkça ayarlayarak bu varsayılanı geçersiz kılabilirsiniz ve bu da varsayılan olarak alt öğeler tarafından devralınır. Bir öğede DataContext'in açıkça ayarlanması, aynı kaynağı kullanan birden çok bağlamaya sahip olmak istediğinizde kullanışlıdır.

Bağlama nesnesinin source özelliği vardır ve bu özellik varsayılan olarak bağlamanın bildirildiği UI öğesinin DataContext değerine ayarlanır. Bağlamada Source, RelativeSource veya ElementName öğesini açıkça ayarlayarak bu varsayılanı geçersiz kılabilirsiniz (ayrıntılar için bkz. {Binding} ).

DataTemplate içinde DataContext otomatik olarak şablonlanan veri nesnesine ayarlanır. Aşağıda verilen örnek, Title ve Description adlı dize özelliklerine sahip herhangi bir türde bir koleksiyona bağlı öğe denetiminin ItemTemplate değeri olarak kullanılabilir.

<DataTemplate x:Key="SimpleItemTemplate">
    <StackPanel Orientation="Vertical" Height="50">
      <TextBlock Text="{Binding Title}"/>
      <TextBlock Text="{Binding Description"/>
    </StackPanel>
  </DataTemplate>

Uyarı

Varsayılan olarak, TextBox.Text'de yapılan değişiklikler TextBox odağı kaybettiğinde iki yönlü bağlı bir kaynağa gönderilir. Her kullanıcı tuş vuruşu sonrasında değişikliklerin gönderilmesine neden olmak için, işaretlemedeki bağlamada UpdateSourceTriggerözelliğini PropertyChanged olarak ayarlayın. Ayrıca UpdateSourceTrigger'ıAçık olarak ayarlayarak, değişikliklerin kaynağa ne zaman gönderileceğini tamamen denetleyebilirsiniz. Daha sonra metin kutusundaki olayları işlersiniz (genellikle TextBox.TextChanged), bindingExpression nesnesi almak için hedefte GetBindingExpression çağrısı yapın ve son olarak veri kaynağını program aracılığıyla güncelleştirmek için BindingExpression.UpdateSource'u çağırın.

Path özelliği iç içe özelliklere, ekli özelliklere ve tamsayı ve dize dizin oluşturucularına bağlama için çeşitli söz dizimi seçeneklerini destekler. Daha fazla bilgi için bkz . Özellik yolu söz dizimi. Dize dizin oluşturucularına bağlama, ICustomPropertyProvider uygulamak zorunda kalmadan dinamik özelliklere bağlamanın etkisini sağlar. ElementName özelliği, öğeden öğeye bağlama için kullanışlıdır. RelativeSource özelliğinin çeşitli kullanımları vardır ve bunlardan biri ControlTemplate içindeki şablon bağlamaya daha güçlü bir alternatiftir. Diğer ayarlar için bkz . {Binding} işaretleme uzantısı ve Bağlama sınıfı.

Kaynak ve hedef aynı türde değilse ne olur?

Boole özelliğinin değerine göre kullanıcı arabirimi öğesinin görünürlüğünü denetlemek veya sayısal bir değerin aralığı veya eğiliminin işlevi olan bir renkle ui öğesini işlemek veya dize bekleyen bir UI öğesi özelliğinde tarih ve/veya saat değeri görüntülemek istiyorsanız, ardından değerleri bir türden diğerine dönüştürmeniz gerekir. Doğru çözümün bağlama kaynak sınıfınızdan doğru türün başka bir özelliğini kullanıma sunma ve dönüştürme mantığını orada kapsüllenmiş ve test edilebilir durumda tutmak olduğu durumlar olacaktır. Ancak bu, kaynak ve hedef özelliklerden oluşan çok sayıda veya büyük bileşimlere sahip olduğunuzda esnek veya ölçeklenebilir değildir. Bu durumda birkaç seçeneğiniz vardır:

  • {x:Bind} kullanıyorsanız, bu dönüştürmeyi yapmak için doğrudan bir işleve bağlanabilirsiniz
  • Alternatif olarak, dönüştürmeyi gerçekleştirmek için tasarlanmış bir nesne olan bir değer dönüştürücüsü de belirtebilirsiniz

Değer Dönüştürücüleri

Burada, bir DateTime değerini ay içeren bir dize değerine dönüştüren tek seferlik veya tek yönlü bağlamaya uygun bir değer dönüştürücüsü bulunmaktadır. sınıfı IValueConverter uygular.

public class DateToStringConverter : IValueConverter
{
    // Define the Convert method to convert a DateTime value to 
    // a month string.
    public object Convert(object value, Type targetType, 
        object parameter, string language)
    {
        // value is the data from the source object.
        DateTime thisdate = (DateTime)value;
        int monthnum = thisdate.Month;
        string month;
        switch (monthnum)
        {
            case 1:
                month = "January";
                break;
            case 2:
                month = "February";
                break;
            default:
                month = "Month not found";
                break;
        }
        // Return the value to pass to the target.
        return month;
    }

    // ConvertBack is not implemented for a OneWay binding.
    public object ConvertBack(object value, Type targetType, 
        object parameter, string language)
    {
        throw new NotImplementedException();
    }
}
// See the "Formatting or converting data values for display" section in the "Data binding overview" topic.

Bağlama nesne işaretlemenizde bu değer dönüştürücüsünüzü şu şekilde tüketirsiniz.

<UserControl.Resources>
  <local:DateToStringConverter x:Key="Converter1"/>
</UserControl.Resources>
...
<TextBlock Grid.Column="0" 
  Text="{x:Bind ViewModel.Month, Converter={StaticResource Converter1}}"/>
<TextBlock Grid.Column="0" 
  Text="{Binding Month, Converter={StaticResource Converter1}}"/>

Bağlama için Converter parametresi tanımlanmışsa bağlama altyapısı Convert ve ConvertBack yöntemlerini çağırır. Kaynaktan veri geçirildiğinde bağlama altyapısı Convert'i çağırır ve döndürülen verileri hedefe geçirir. Veriler hedeften geçirildiğinde (iki yönlü bağlama için), bağlama altyapısı ConvertBack'i çağırır ve döndürülen verileri kaynağa geçirir.

Dönüştürücü ayrıca isteğe bağlı parametrelere de sahiptir: Dönüştürmede kullanılacak dilin belirtilmesine olanak tanıyan ConverterLanguage ve dönüştürme mantığı için bir parametrenin geçirilmesine olanak tanıyan ConverterParameter. Dönüştürücü parametresi kullanan bir örnek için bkz. IValueConverter.

Uyarı

Dönüştürmede bir hata varsa, özel durum oluşturma. Bunun yerine, veri aktarımını durduracak DependencyProperty.UnsetValue değerini döndürebilirsiniz.

Bağlama kaynağı çözümlenemediğinde kullanılacak varsayılan değeri görüntülemek için, işaretlemedeki bağlama nesnesinde FallbackValue özelliğini ayarlayın. Bu, dönüştürme ve biçimlendirme hatalarını işlemek için yararlıdır. Ayrıca, heterojen türlerden oluşan ilişkili bir koleksiyondaki tüm nesnelerde varolmayabilecek kaynak özelliklere bağlanmak da yararlıdır.

Metin denetimini dize olmayan bir değere bağlarsanız, veri bağlama altyapısı değeri dizeye dönüştürür. Değer bir başvuru türüyse, veri bağlama altyapısı ICustomPropertyProvider.GetStringRepresentation veya varsa IStringable.ToString çağrısı yaparak dize değerini alır ve aksi takdirde Object.ToString'i çağırır. Ancak, bağlama altyapısının temel sınıf uygulamasını gizleyen herhangi bir ToString uygulamasını yoksayacağını unutmayın. Alt sınıf uygulamaları bunun yerine temel sınıf ToString yöntemini geçersiz kılmalıdır. Benzer şekilde, yerel dillerde tüm yönetilen nesneler ICustomPropertyProvider ve IStringable'ı uyguluyor gibi görünür. Ancak, GetStringRepresentation ve IStringable.ToString'e yapılan tüm çağrılar Object.ToString'e veya bu yöntemin geçersiz kılınmasına yönlendirilir ve hiçbir zaman temel sınıf uygulamasını gizleyen yeni bir ToString uygulamasına yönlendirilmez.

Uyarı

Windows 10, sürüm 1607'den itibaren XAML çerçevesi yerleşik bir Boole to Visibility dönüştürücüsü sağlar. Dönüştürücü Visible sabit listesi değeriyle true ve Daraltılmış olarak false değerlerini eşler, böylece bir visibility özelliğini dönüştürücü oluşturmadan boole değerine bağlayabilirsiniz. Yerleşik dönüştürücüsü kullanmak için uygulamanızın en düşük hedef SDK sürümü 14393 veya üzeri olmalıdır. Uygulamanız Windows 10'un önceki sürümlerini hedeflediğinde kullanamazsınız. Hedef sürümler hakkında daha fazla bilgi için bkz . Sürüm uyarlamalı kod.

{x:Bind} içinde işlev bağlaması

{x:Bind}, bağlama yolundaki son adımın işlev olmasını sağlar. Bu, dönüştürmeleri gerçekleştirmek ve birden fazla özelliğe bağlı bağlamalar gerçekleştirmek için kullanılabilir. Bkz. x:Bind İşlevleri

Öğeden öğeye bağlama

Bir XAML öğesinin özelliğini başka bir XAML öğesinin özelliğine bağlayabilirsiniz. Bunun işaretlemede nasıl göründüğüne dair bir örnek aşağıda verilmiştır.

<TextBox x:Name="myTextBox" />
<TextBlock Text="{x:Bind myTextBox.Text, Mode=OneWay}" />

Önemli

C++/WinRT kullanarak öğeden öğeye bağlama için gerekli iş akışı için bkz. Öğeden öğeye bağlama.

{x:Bind} ile kaynak sözlükleri

{x:Bind} işaretleme uzantısı kod oluşturma işlemine bağlıdır, bu nedenle InitializeComponent'i çağıran bir oluşturucu içeren arka planda kod dosyası gerekir (oluşturulan kodu başlatmak için). Kaynak sözlüğünü, dosya adına başvurmak yerine türünün örneğini ( InitializeComponent'in çağrılması için) başlatarak yeniden kullanırsınız. Burada, var olan bir kaynak sözlüğüne sahipseniz ve içinde {x:Bind} kullanmak istiyorsanız yapmanız gerekenlere bir örnek verilmiştir.

TemplatesResourceDictionary.xaml

<ResourceDictionary
    x:Class="ExampleNamespace.TemplatesResourceDictionary"
    .....
    xmlns:examplenamespace="using:ExampleNamespace">
    
    <DataTemplate x:Key="EmployeeTemplate" x:DataType="examplenamespace:IEmployee">
        <Grid>
            <TextBlock Text="{x:Bind Name}"/>
        </Grid>
    </DataTemplate>
</ResourceDictionary>

TemplatesResourceDictionary.xaml.cs

using Windows.UI.Xaml.Data;
 
namespace ExampleNamespace
{
    public partial class TemplatesResourceDictionary
    {
        public TemplatesResourceDictionary()
        {
            InitializeComponent();
        }
    }
}

MainPage.xaml

<Page x:Class="ExampleNamespace.MainPage"
    ....
    xmlns:examplenamespace="using:ExampleNamespace">

    <Page.Resources>
        <ResourceDictionary>
            .... 
            <ResourceDictionary.MergedDictionaries>
                <examplenamespace:TemplatesResourceDictionary/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Page.Resources>
</Page>

{x:Bind} ve {Binding} yeniden kullanılabilir bir Stilde karıştırılır

Önceki örnekte DataTemplates'te {x:Bind} kullanıldığı gösterildi ancak hem {x:Bind} hem de {Binding} işaretleme uzantılarını birleştiren yeniden kullanılabilir Stiller de oluşturabilirsiniz. Bazı özellikleri {x:Bind} kullanarak derleme zamanı bilinen değerlerine ve diğer özellikleri {Binding} kullanarak çalışma zamanı DataContext değerlerine bağlamak istediğinizde bu yararlı olur.

Her iki bağlama yaklaşımını da kullanan yeniden kullanılabilir bir Düğme stilinin nasıl oluşturulacağını gösteren bir örnek aşağıda verilmiştir:

TemplatesResourceDictionary.xaml

<ResourceDictionary
    x:Class="ExampleNamespace.TemplatesResourceDictionary"
    .....
    xmlns:examplenamespace="using:ExampleNamespace">
    
    <!-- DataTemplate using x:Bind -->
    <DataTemplate x:Key="EmployeeTemplate" x:DataType="examplenamespace:IEmployee">
        <Grid>
            <TextBlock Text="{x:Bind Name}"/>
        </Grid>
    </DataTemplate>
    
    <!-- Style that mixes x:Bind and Binding -->
    <Style x:Key="CustomButtonStyle" TargetType="Button">
        <Setter Property="Background" Value="{Binding ButtonBackgroundBrush}"/>
        <Setter Property="Foreground" Value="{Binding ButtonForegroundBrush}"/>
        <Setter Property="FontSize" Value="16"/>
        <Setter Property="Margin" Value="4"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border x:Name="RootBorder"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            CornerRadius="4">
                        <StackPanel Orientation="Horizontal" 
                                    HorizontalAlignment="Center"
                                    VerticalAlignment="Center">
                            <!-- x:Bind to a static property or page-level property -->
                            <Ellipse Width="8" Height="8" 
                                     Fill="{x:Bind DefaultIndicatorBrush}" 
                                     Margin="0,0,8,0"/>
                            <!-- Binding to DataContext -->
                            <ContentPresenter x:Name="ContentPresenter"
                                              Content="{TemplateBinding Content}"
                                              Foreground="{TemplateBinding Foreground}"
                                              FontSize="{TemplateBinding FontSize}"/>
                        </StackPanel>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="PointerOver">
                                    <VisualState.Setters>
                                        <!-- Binding to DataContext for hover color -->
                                        <Setter Target="RootBorder.Background" 
                                                Value="{Binding ButtonHoverBrush}"/>
                                    </VisualState.Setters>
                                </VisualState>
                                <VisualState x:Name="Pressed">
                                    <VisualState.Setters>
                                        <!-- x:Bind to a compile-time known resource -->
                                        <Setter Target="RootBorder.Background" 
                                                Value="{x:Bind DefaultPressedBrush}"/>
                                    </VisualState.Setters>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

TemplatesResourceDictionary.xaml.cs

using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;
 
namespace ExampleNamespace
{
    public partial class TemplatesResourceDictionary
    {
        public TemplatesResourceDictionary()
        {
            InitializeComponent();
        }
        
        // Properties for x:Bind - these are compile-time bound
        public SolidColorBrush DefaultIndicatorBrush { get; } = 
            new SolidColorBrush(Colors.Green);
            
        public SolidColorBrush DefaultPressedBrush { get; } = 
            new SolidColorBrush(Colors.DarkGray);
    }
}

Çalışma zamanı değerleri sağlayan bir ViewModel ile MainPage.xaml dosyasında kullanım:

<Page x:Class="ExampleNamespace.MainPage"
    ....
    xmlns:examplenamespace="using:ExampleNamespace">

    <Page.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <examplenamespace:TemplatesResourceDictionary/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Page.Resources>
    
    <Page.DataContext>
        <examplenamespace:ButtonThemeViewModel/>
    </Page.DataContext>

    <StackPanel Margin="20">
        <!-- This button uses the mixed binding style -->
        <Button Content="Save" Style="{StaticResource CustomButtonStyle}"/>
        <Button Content="Cancel" Style="{StaticResource CustomButtonStyle}"/>
    </StackPanel>
</Page>

ButtonThemeViewModel.cs (çalışma zamanı bağlama değerleri sağlayan DataContext):

using System.ComponentModel;
using Windows.UI;
using Windows.UI.Xaml.Media;

namespace ExampleNamespace
{
    public class ButtonThemeViewModel : INotifyPropertyChanged
    {
        private SolidColorBrush _buttonBackgroundBrush = new SolidColorBrush(Colors.LightBlue);
        private SolidColorBrush _buttonForegroundBrush = new SolidColorBrush(Colors.DarkBlue);
        private SolidColorBrush _buttonHoverBrush = new SolidColorBrush(Colors.LightCyan);

        public SolidColorBrush ButtonBackgroundBrush
        {
            get => _buttonBackgroundBrush;
            set
            {
                _buttonBackgroundBrush = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ButtonBackgroundBrush)));
            }
        }

        public SolidColorBrush ButtonForegroundBrush
        {
            get => _buttonForegroundBrush;
            set
            {
                _buttonForegroundBrush = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ButtonForegroundBrush)));
            }
        }

        public SolidColorBrush ButtonHoverBrush
        {
            get => _buttonHoverBrush;
            set
            {
                _buttonHoverBrush = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ButtonHoverBrush)));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

Bu örnekte:

  • {Binding} , DataContext'e bağlı özellikler için kullanılır (ButtonBackgroundBrush, ButtonForegroundBrush, ButtonHoverBrush)
  • {x:Bind} , bilinen derleme zamanı olan ve ResourceDictionary'nin kendisine ait özellikler için kullanılır (DefaultIndicatorBrush, DefaultPressedBrush)
  • Stil yeniden kullanılabilir ve herhangi bir Düğmeye uygulanabilir
  • Statik öğeler için {x:Bind} performansından yararlanmaya devam ederken DataContext aracılığıyla çalışma zamanı temalı çalışma zamanı yapılabilir

Olay bağlama ve ICommand

{x:Bind} , olay bağlama adlı bir özelliği destekler. Bu özellik ile bağlama kullanarak bir olayın işleyicisini belirtebilirsiniz. Bu, arka planda kod dosyasındaki bir yöntemle olayları işlemeye ek bir seçenektir. MainPage sınıfınızda bir RootFrame özelliği olduğunu varsayalım.

public sealed partial class MainPage : Page
{
    ...
    public Frame RootFrame { get { return Window.Current.Content as Frame; } }
}

Ardından, bir düğmenin Click olayını RootFrame özelliği tarafından döndürülen Frame nesnesinde bir yönteme bağlayabilirsiniz. Düğmenin IsEnabled özelliğini de aynı Çerçevenin başka bir üyesine bağladığımıza dikkat edin.

<AppBarButton Icon="Forward" IsCompact="True"
IsEnabled="{x:Bind RootFrame.CanGoForward, Mode=OneWay}"
Click="{x:Bind RootFrame.GoForward}"/>

Bu teknikle bir olayı işlemek için aşırı yüklenmiş yöntemler kullanılamaz. Ayrıca, olayı işleyen yöntemin parametreleri varsa, bunların tümü sırasıyla tüm olay parametrelerinin türlerinden atanabilir olmalıdır. Bu durumda , Frame.GoForward aşırı yüklenmez ve parametresi yoktur (ancak iki nesne parametresi olsa bile geçerli olacaktır). Ancak Frame.GoBack aşırı yüklenmiştir, bu nedenle bu yöntemi bu teknikle kullanamayız.

Olay bağlama tekniği, komutları uygulamaya ve kullanmaya benzer (komut, ICommand arabirimini uygulayan bir nesne döndüren bir özelliktir). Hem {x:Bind} hem de {Binding} komutlarla çalışır. Komut düzenini birden çok kez uygulamanız gerekmeyecek şekilde, QuizGame örneğinde ("Ortak" klasöründe) bulabileceğiniz DelegateCommand yardımcı sınıfını kullanabilirsiniz.

Klasör veya dosya koleksiyonuna bağlama

Klasör ve dosya verilerini almak için Windows.Storage ad alanında API'leri kullanabilirsiniz. Ancak, çeşitli GetFilesAsync, GetFoldersAsync ve GetItemsAsync yöntemleri liste denetimlerine bağlama için uygun değerler döndürmez. Bunun yerine, FileInformationFactory sınıfının GetVirtualizedFilesVector, GetVirtualizedFoldersVector ve GetVirtualizedItemsVector yöntemlerinin dönüş değerlerine bağlamanız gerekir. StorageDataSource ve GetVirtualizedFilesVector örneğindeki aşağıdaki kod örneği tipik kullanım desenini gösterir. Uygulama paketi bildiriminizde picturesLibrary özelliğini bildirmeyi unutmayın ve Resimler kitaplığı klasörünüzde resimler olduğunu onaylayın.

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    var library = Windows.Storage.KnownFolders.PicturesLibrary;
    var queryOptions = new Windows.Storage.Search.QueryOptions();
    queryOptions.FolderDepth = Windows.Storage.Search.FolderDepth.Deep;
    queryOptions.IndexerOption = Windows.Storage.Search.IndexerOption.UseIndexerWhenAvailable;

    var fileQuery = library.CreateFileQueryWithOptions(queryOptions);

    var fif = new Windows.Storage.BulkAccess.FileInformationFactory(
        fileQuery,
        Windows.Storage.FileProperties.ThumbnailMode.PicturesView,
        190,
        Windows.Storage.FileProperties.ThumbnailOptions.UseCurrentScale,
        false
        );

    var dataSource = fif.GetVirtualizedFilesVector();
    this.PicturesListView.ItemsSource = dataSource;
}

Bu yaklaşımı genellikle dosya ve klasör bilgilerinin salt okunur bir görünümünü oluşturmak için kullanırsınız. Dosya ve klasör özelliklerine iki yönlü bağlamalar oluşturabilirsiniz; örneğin, kullanıcıların müzik görünümünde bir şarkıyı derecelendirmesine izin vermek için. Ancak, uygun SavePropertiesAsync yöntemini (örneğin, MusicProperties.SavePropertiesAsync) çağırana kadar değişiklikler kalıcı olmaz. Öğe odağı kaybettiğinde değişiklikleri işlemeniz gerekir çünkü bu işlem seçim sıfırlamasını tetikler.

Bu tekniği kullanarak iki yönlü bağlamanın yalnızca Müzik gibi dizine alınan konumlarla çalıştığını unutmayın. FolderInformation.GetIndexedStateAsync yöntemini çağırarak bir konumun dizine alınıp alınmadığını belirleyebilirsiniz.

Ayrıca, sanallaştırılmış vektörlerin, değerlerini doldurmadan önce bazı öğeler için null döndürebileceğini unutmayın. Örneğin, sanallaştırılmış vektöre bağlı bir liste denetiminin SelectedItem değerini kullanmadan önce null değerini veya bunun yerine SelectedIndex'i kullanmanız gerekir.

Anahtara göre gruplandırılmış verilere bağlama

Düz bir öğe koleksiyonu (örneğin, BookSku sınıfı tarafından temsil edilen kitaplar) alırsanız ve öğeleri anahtar olarak ortak bir özellik kullanarak gruplandırıyorsanız (örneğin , BookSku.AuthorName özelliği), sonuç gruplandırılmış veri olarak adlandırılır. Verileri gruplandırdığınızda, bu artık düz bir koleksiyon değildir. Gruplandırılmış veriler, her grup nesnesinin sahip olduğu bir grup nesneleri koleksiyonudur

  • bir anahtar ve
  • özelliği bu anahtarla eşleşen öğe koleksiyonu.

Kitap örneğini yeniden almak için, kitapları yazar adına göre gruplandırma sonucu, her grubun sahip olduğu yazar adı gruplarından oluşan bir koleksiyonla sonuçlanır

  • bir yazar adı olan bir anahtar ve
  • AuthorName özelliği grubun anahtarıyla eşleşen BookSkukoleksiyonu.

Genel olarak, bir koleksiyonu görüntülemek için bir öğe denetiminin ItemsSource'unu (ListView veya GridView gibi) doğrudan koleksiyon döndüren bir özelliğe bağlarsınız. Bu düz bir öğe koleksiyonuysa, özel bir şey yapmanız gerekmez. Ancak grup nesnelerinin bir koleksiyonuysa (gruplandırılmış verilere bağlanırken olduğu gibi), öğe denetimi ile bağlama kaynağı arasında yer alan CollectionViewSource adlı bir ara nesnenin hizmetlerine ihtiyacınız vardır. CollectionViewSource'ı gruplandırılmış verileri döndüren özelliğe bağlarsınız ve öğe denetimini CollectionViewSource'a bağlarsınız. Bir CollectionViewSource'un ek bir değer eklemesi, geçerli öğeyi izlemesidir; böylece birden fazla öğe denetimini eşitlenmiş durumda tutarak tümünü aynı CollectionViewSource'a bağlayabilirsiniz. Geçerli öğeye, CollectionViewSource.View özelliği tarafından döndürülen nesnenin ICollectionView.CurrentItem özelliği aracılığıyla program aracılığıyla da erişebilirsiniz.

CollectionViewSource'un gruplandırma tesisini etkinleştirmek için IsSourceGrouped değerini true olarak ayarlayın. ItemsPath özelliğini de ayarlamanız gerekip gerekmediği, grup nesnelerinizi tam olarak nasıl yazdığınıza bağlıdır. Grup nesnesi yazmanın iki yolu vardır: "is-a-group" deseni ve "has-a-group" deseni. "grup-a-grubu" deseninde, grup nesnesi bir koleksiyon türünden türetilir (örneğin, Liste<T>), bu nedenle grup nesnesi aslında öğe grubudur. Bu desenle ItemsPath'i ayarlamanız gerekmez. "Has-a-group" deseninde, grup nesnesi koleksiyon türünde bir veya daha fazla özelliğe ( Liste<T> gibi) sahiptir, bu nedenle grubun bir özellik biçiminde bir öğe grubu (veya birkaç özellik biçiminde birkaç öğe grubu) vardır. Bu desenle ItemsPath'i öğe grubunu içeren özelliğin adına ayarlamanız gerekir.

Aşağıdaki örnekte "has-a-group" deseni gösterilmektedir. Sayfa sınıfı, görünüm modelimizin bir örneğini döndüren ViewModel adlı bir özelliğe sahiptir. CollectionViewSource, görünüm modelinin Authors özelliğine bağlanır (Yazarlar grup nesnelerinin koleksiyonudur) ve gruplandırılmış öğeleri içeren Author.BookSkus özelliği olduğunu belirtir. Son olarak , GridViewCollectionViewSource'a bağlıdır ve öğeleri gruplar halinde işleyebilmesi için grup stili tanımlanmıştır.

<Page.Resources>
    <CollectionViewSource
    x:Name="AuthorHasACollectionOfBookSku"
    Source="{x:Bind ViewModel.Authors}"
    IsSourceGrouped="true"
    ItemsPath="BookSkus"/>
</Page.Resources>
...
<GridView
ItemsSource="{x:Bind AuthorHasACollectionOfBookSku}" ...>
    <GridView.GroupStyle>
        <GroupStyle
            HeaderTemplate="{StaticResource AuthorGroupHeaderTemplateWide}" ... />
    </GridView.GroupStyle>
</GridView>

"Grupdur" desenini iki yoldan biriyle uygulayabilirsiniz. Bunun bir yolu kendi grup sınıfınızı yazmaktır. Sınıfı Liste<T'den> türet (burada T , öğelerin türüdür). Örneğin, public class Author : List<BookSku>. İkinci yol, BookSku öğelerinin özellik değerleri gibi grup nesnelerini (ve grup sınıfını) dinamik olarak oluşturmak için LINQ ifadesi kullanmaktır. Öğelerin yalnızca düz bir listesini korumak ve bunları anında gruplandırma yaklaşımı, bulut hizmetinden verilere erişen bir uygulamaya özgüdür. Yazar ve Tarz gibi özel grup sınıflarına gerek kalmadan kitapları yazara veya tarza göre (örneğin) gruplandırma esnekliğine sahip olursunuz.

Aşağıdaki örnekte LINQ kullanan "is-a-group" deseni gösterilmektedir. Bu kez kitapları, grup üst bilgilerinde tarz adıyla görüntülenen türe göre gruplandırıyoruz. Bu, grup Anahtarı değerine başvuruda " Anahtar " özellik yolu ile gösterilir.

using System.Linq;
...
private IOrderedEnumerable<IGrouping<string, BookSku>> genres;

public IOrderedEnumerable<IGrouping<string, BookSku>> Genres
{
    get
    {
        if (this.genres == null)
        {
            this.genres = from book in this.bookSkus
                          group book by book.genre into grp
                          orderby grp.Key
                          select grp;
        }
        return this.genres;
    }
}

Veri şablonlarıyla {x:Bind} kullanırken x:DataType değeri ayarlayarak bağlı olan türü belirtmemiz gerektiğini unutmayın. Tür genelse, bunu işaretlemede ifade edemiyoruz, bu nedenle grup stili üst bilgi şablonu yerine {Binding} kullanmamız gerekiyor.

    <Grid.Resources>
        <CollectionViewSource x:Name="GenreIsACollectionOfBookSku"
        Source="{x:Bind Genres}"
        IsSourceGrouped="true"/>
    </Grid.Resources>
    <GridView ItemsSource="{x:Bind GenreIsACollectionOfBookSku}">
        <GridView.ItemTemplate x:DataType="local:BookTemplate">
            <DataTemplate>
                <TextBlock Text="{x:Bind Title}"/>
            </DataTemplate>
        </GridView.ItemTemplate>
        <GridView.GroupStyle>
            <GroupStyle>
                <GroupStyle.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Key}"/>
                    </DataTemplate>
                </GroupStyle.HeaderTemplate>
            </GroupStyle>
        </GridView.GroupStyle>
    </GridView>

SemanticZoom denetimi, kullanıcılarınızın gruplandırılmış verileri görüntülemesi ve bu verilerde gezinmesi için harika bir yoldur. Bookstore2 örnek uygulaması SemanticZoom'un nasıl kullanılacağını gösterir. Bu uygulamada, yazara göre gruplandırılmış kitapların listesini (yakınlaştırılmış görünüm) görüntüleyebilir veya yazarların atlama listesini (uzaklaştırılmış görünüm) görmek için uzaklaştırabilirsiniz. Atlama listesi, kitap listesinde gezinmekten çok daha hızlı gezinmeyi sağlar. Yakınlaştırılan ve uzaklaştırılan görünümler aslında aynı CollectionViewSource'a bağlı ListView veya GridView denetimleridir.

SemanticZoom çizimi

Hiyerarşik verilere (kategoriler içindeki alt kategoriler gibi) bağlandığınızda, kullanıcı arabiriminizdeki hiyerarşik düzeyleri bir dizi öğe denetimiyle görüntülemeyi seçebilirsiniz. Bir öğe denetimindeki seçim, sonraki öğe denetimlerinin içeriğini belirler. Her listeyi kendi CollectionViewSource'a bağlayarak ve CollectionViewSource örneklerini zincirde birbirine bağlayarak listeleri eşitlenmiş olarak tutabilirsiniz. Buna ana/ayrıntılar (veya liste/ayrıntılar) görünümü adı verilir. Daha fazla bilgi için bkz. Hiyerarşik verilere bağlanma ve ana/ayrıntılar görünümü oluşturma.

Veri bağlama sorunlarını tanılama ve hata ayıklama

Bağlama işaretlemeniz özelliklerin adlarını (ve C# için bazen alanlar ve yöntemler) içerir. Bu nedenle, bir özelliği yeniden adlandırdığınızda, buna başvuran bağlamaları da değiştirmeniz gerekir. Bunu unutmak, tipik bir veri bağlama hatası örneğine yol açar ve uygulamanız derlenmez veya düzgün çalışmaz.

{x:Bind} ve {Binding} tarafından oluşturulan bağlama nesneleri büyük ölçüde işlevsel olarak eşdeğerdir. Ancak {x:Bind} bağlama kaynağı için tür bilgilerine sahip ve derleme zamanında kaynak kodu oluşturuyor. {x:Bind} ile kodunuzun geri kalanıyla aynı türde bir sorun algılama elde edersiniz. Buna bağlama ifadelerinizin derleme zamanı doğrulaması ve sayfanızın kısmi sınıfı olarak oluşturulan kaynak kodda kesme noktaları ayarlayarak hata ayıklama dahildir. Bu sınıflar klasörünüzdeki obj dosyalarda (C#için) <view name>.g.csgibi adlarla bulunabilir. Bağlamayla ilgili bir sorununuz varsa Microsoft Visual Studio hata ayıklayıcısında İşlenmeyen Özel Durumları Kes seçeneğini açın. Hata ayıklayıcı bu noktada yürütmeyi bozar ve ardından neyin yanlış gittiğinin hatalarını ayıklayabilirsiniz. {x:Bind} tarafından oluşturulan kod, bağlama kaynak düğümleri grafiğinin her bölümü için aynı deseni izler ve soruna yol açan çağrıların sırasını saptamaya yardımcı olması için Çağrı Yığını penceresindeki bilgileri kullanabilirsiniz.

{Binding} bağlama kaynağı için tür bilgilerine sahip değil. Ancak uygulamanızı hata ayıklayıcı ekli olarak çalıştırdığınızda, bağlama hataları Visual Studio'daki Çıkış penceresinde görüntülenir.

Kodda bağlama oluşturma

Not Kodda {x:Bind} bağlamaları oluşturamadığınız için bu bölüm yalnızca {Binding} için geçerlidir. Ancak, {x:Bind} uygulamasının aynı avantajlarından bazıları DependencyObject.RegisterPropertyChangedCallback ile elde edilebilir ve bu sayede herhangi bir bağımlılık özelliğinde değişiklik bildirimlerine kaydolabilirsiniz.

Kullanıcı arabirimi öğelerini XAML yerine yordam kodu kullanarak verilere de bağlayabilirsiniz. Bunu yapmak için yeni bir Binding nesnesi oluşturun, uygun özellikleri ayarlayın, ardından FrameworkElement.SetBinding veya BindingOperations.SetBinding öğesini çağırın. Bağlama özelliği değerlerini çalışma zamanında seçmek veya birden çok denetim arasında tek bir bağlama paylaşmak istediğinizde program aracılığıyla bağlama oluşturmak yararlı olur. Ancak, SetBinding'i çağırdıktan sonra bağlama özelliği değerlerini değiştiremeyeceğinizi unutmayın.

Aşağıdaki örnekte kodda bağlamanın nasıl uygulanacakları gösterilmektedir.

<TextBox x:Name="MyTextBox" Text="Text"/>
// Create an instance of the MyColors class 
// that implements INotifyPropertyChanged.
MyColors textcolor = new MyColors();

// Brush1 is set to be a SolidColorBrush with the value Red.
textcolor.Brush1 = new SolidColorBrush(Colors.Red);

// Set the DataContext of the TextBox MyTextBox.
MyTextBox.DataContext = textcolor;

// Create the binding and associate it with the text box.
Binding binding = new Binding() { Path = new PropertyPath("Brush1") };
MyTextBox.SetBinding(TextBox.ForegroundProperty, binding);
' Create an instance of the MyColors class 
' that implements INotifyPropertyChanged. 
Dim textcolor As New MyColors()

' Brush1 is set to be a SolidColorBrush with the value Red. 
textcolor.Brush1 = New SolidColorBrush(Colors.Red)

' Set the DataContext of the TextBox MyTextBox. 
MyTextBox.DataContext = textcolor

' Create the binding and associate it with the text box.
Dim binding As New Binding() With {.Path = New PropertyPath("Brush1")}
MyTextBox.SetBinding(TextBox.ForegroundProperty, binding)

{x:Bind} ve {Binding} özellik karşılaştırması

Özellik {x:Bind} ile {Binding} karşılaştırması Notes
Yol varsayılan özelliktir {x:Bind a.b.c}
-
{Binding a.b.c}
Path özelliği {x:Bind Path=a.b.c}
-
{Binding Path=a.b.c}
x:Bind'te, Path varsayılan olarak DataContext'te değil, Sayfa'da kök olarak oluşturulur.
Indexer {x:Bind Groups[2].Title}
-
{Binding Groups[2].Title}
Koleksiyonda belirtilen öğeye bağlar. Yalnızca tamsayı tabanlı dizinler desteklenir.
Ekli özellikler {x:Bind Button22.(Grid.Row)}
-
{Binding Button22.(Grid.Row)}
Eklenen özellikler parantezler kullanılarak belirtilir. Özellik bir XAML ad alanında bildirilmemişse, ön ek olarak belgenin başındaki bir kod ad alanına eşlenmesi gereken bir xml ad alanı ekleyin.
Döküm {x:Bind groups[0].(data:SampleDataGroup.Title)}
-
{Binding} için gerekli değil.
Atamalar parantezler kullanılarak belirtilir. Özellik bir XAML ad alanında bildirilmemişse, ön ek olarak belgenin başındaki bir kod ad alanına eşlenmesi gereken bir xml ad alanı ekleyin.
Dönüştürücü {x:Bind IsShown, Converter={StaticResource BoolToVisibility}}
-
{Binding IsShown, Converter={StaticResource BoolToVisibility}}
Dönüştürücüler Page/ResourceDictionary kökünde veya App.xaml içinde bildirilmelidir.
ConverterParameter, ConverterLanguage {x:Bind IsShown, Converter={StaticResource BoolToVisibility}, ConverterParameter=One, ConverterLanguage=fr-fr}
-
{Binding IsShown, Converter={StaticResource BoolToVisibility}, ConverterParameter=One, ConverterLanguage=fr-fr}
Dönüştürücüler Page/ResourceDictionary kökünde veya App.xaml içinde bildirilmelidir.
TargetNullValue {x:Bind Name, TargetNullValue=0}
-
{Binding Name, TargetNullValue=0}
Bağlama ifadesinin yaprağı null olduğunda kullanılır. Dize değeri için tek tırnak işareti kullanın.
FallbackValue {x:Bind Name, FallbackValue='empty'}
-
{Binding Name, FallbackValue='empty'}
Bağlama yolunun herhangi bir bölümü (yaprak hariç) null olduğunda kullanılır.
ÖğeAdı {x:Bind slider1.Value}
-
{Binding Value, ElementName=slider1}
{x:Bind} ile bir alana bağlanıyorsunuz; Yol varsayılan olarak Sayfa'ya kök olarak eklenir, bu nedenle adlandırılmış öğelere kendi alanı üzerinden erişilebilir.
RelativeSource: Self <Rectangle x:Name="rect1" Width="200" Height="{x:Bind rect1.Width}" ... />
-
<Rectangle Width="200" Height="{Binding Width, RelativeSource={RelativeSource Self}}" ... />
{x:Bind} ile öğeyi adlandırın ve Path'de öğesinin adını kullanın.
RelativeSource: TemplatedParent {x:Bind} için gerekli değil
-
{Binding <path>, RelativeSource={RelativeSource TemplatedParent}}
ControlTemplate üzerinde {x:Bind} TargetType olması şablon üst öğesine bağlamayı gösterir. {Binding} için Çoğu kullanım için denetim şablonlarında normal şablon bağlama kullanılabilir. Ancak, bir dönüştürücü veya iki yönlü bağlama kullanmanız gereken TemplatedParent kullanın.<
Kaynak {x:Bind} için gerekli değil
-
<ListView ItemsSource="{Binding Orders, Source={StaticResource MyData}}"/>
{x:Bind} için adlandırılmış öğeyi doğrudan kullanabilir, bir özellik veya statik yol kullanabilirsiniz.
Mode {x:Bind Name, Mode=OneWay}
-
{Binding Name, Mode=TwoWay}
Mod OneTime, OneWay veya TwoWay olabilir. {x:Bind} varsayılan olarak OneTime; {Binding} varsayılan olarak OneWay'i kullanır.
UpdateSourceTrigger {x:Bind Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}
-
{Binding UpdateSourceTrigger=PropertyChanged}
UpdateSourceTrigger Default, LostFocus veya PropertyChanged olabilir. {x:Bind} UpdateSourceTrigger=Explicit'i desteklemiyor. {x:Bind}, LostFocus davranışını kullandığı TextBox.Text dışındaki tüm durumlar için PropertyChanged davranışını kullanıyor.