Megosztás:


Részletes Windows-adatkötés

Ez a cikk a Microsoft.UI.Xaml.Data névtér API-jait használó WinUI-adatkötési funkciókat ismerteti.

Megjegyzés:

Ez a témakör részletesen ismerteti az adatkötési funkciókat. Rövid, gyakorlati bevezetésért tekintse meg az adatkötés áttekintését.

Fontos API-k

Bevezetés

Az adatkötés olyan technika, amellyel az alkalmazás felhasználói felülete hatékonyan jelenítheti meg és szinkronizálhatja az adatokat. Az adatproblémáknak a felhasználói felülettel kapcsolatos aggodalmaktól való elválasztásával leegyszerűsíti az alkalmazások tervezését, javítja az olvashatóságot, és javítja a karbantarthatóságot.

Az adatkötéssel egyszerűen megjelenítheti az adatforrás értékeit a felhasználói felület első megjelenítésekor, de nem válaszolhat az értékek változásaira. Ezt a kötési módot egyszerinek nevezzük, és jól működik egy olyan érték esetében, amely futásidőben nem változik. Másik lehetőségként dönthet úgy is, hogy "megfigyeli" az értékeket, és módosítja a felhasználói felületet, amikor azok változnak. Ezt a módot egyirányúnak nevezik, és jól működik az írásvédett adatokhoz. Végső soron úgy is dönthet, hogy megfigyeli és frissíti a felhasználói felületen lévő értékeket, így a rendszer automatikusan visszaküldi az adatforrásba a felhasználó által végrehajtott módosításokat. Ezt a módot kétirányúnak nevezik, és jól működik az olvasási-írási adatokhoz. Íme néhány példa.

  • Az egyszeri módban a rendszerképet az aktuális felhasználó fényképéhez kötheti.
  • Az egyirányú módban a ListView-t az újságszakaszok szerint csoportosított valós idejű hírcikkek gyűjteményéhez kötheti.
  • A kétirányú módban a TextBoxot egy ügyfél nevéhez kötheti egy űrlapon.

A módtól függetlenül kétféle kötés létezik, és általában mindkettőt a felhasználói felületi korrektúrában deklarálja. Választhatja a {x:Bind} korrektúrakiterjesztést vagy a {Binding} korrektúrakiterjesztést. Akár a kettő keverékét is használhatja ugyanabban az alkalmazásban – még ugyanazon a felhasználói felületen is. {x:Bind} A Windows 10 UWP-ben új volt, és jobb teljesítménnyel rendelkezik. A jelen témakörben ismertetett összes részlet mindkét kötéstípusra vonatkozik, hacsak nem mondjuk kifejezetten másként.

UWP-mintaalkalmazások, amelyek a(z) {x:Bind} alkalmazást mutatják be

UWP-mintaalkalmazások a(z) {Binding} bemutatásához

Minden kötés magában foglalja ezeket a darabokat

  • Kötési forrás. Ez a forrás biztosítja a kötés adatait. Bármely osztály olyan példánya lehet, amelynek tagjai a felhasználói felületen megjelenítendő értékekkel rendelkeznek.
  • Kötési cél. Ez a cél egy DependencyProperty a FrameworkElement részeként az Ön felhasználói felületén, amely megjeleníti az adatokat.
  • Kötésobjektum. Ez az objektum adatértékeket továbbít a forrásból a célba, és opcionálisan a célból vissza a forrásba. A kötési objektum XAML-betöltéskor jön létre a(z) {x:Bind} vagy {Binding} korrektúrakiterjesztésből.

A következő szakaszokban közelebbről is áttekintheti a kötés forrását, a kötési célt és a kötési objektumot. A szakaszok példaként bemutatják, hogyan lehet a gomb tartalmát egy NextButtonText nevű string tulajdonsághoz kötni, amely egy HostViewModel nevű osztályhoz tartozik.

Kötés forrása

Íme egy olyan osztály alapszintű implementációja, amelyet kötésforrásként használhat.

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

    public string NextButtonText { get; set; }
}

Ennek megvalósítása és tulajdonsága HostViewModelNextButtonTextcsak egyszeri kötés esetén működik. Az egyirányú és a kétirányú kötések azonban rendkívül gyakoriak. Ezekben a kötéstípusokban a felhasználói felület automatikusan frissül a kötésforrás adatértékeinek változásaira reagálva. Ahhoz, hogy az ilyen típusú kötések megfelelően működjenek, a kötésforrást megfigyelhetővé kell tennie a kötési objektumon. Ezért a példánkban, ha egyirányú vagy kétirányú kötést szeretne a tulajdonsághoz NextButtonText , akkor a tulajdonság értékének futásidejű módosításainak megfigyelhetőnek kell lenniük a kötési objektumon.

Ennek egyik módja, ha a DependencyObjectből származtatja a kötésforrást képviselő osztályt, és egy DependencyProperty*-on keresztül elérhetővé tesz egy adatértéket. Így válik megfigyelhetővé egy FrameworkElement . Az A FrameworkElement egy jó kötési forrás közvetlenül a dobozból.

Az osztály megfigyelhetővé tételének egyszerűbb módja – és a már alaposztálysal rendelkező osztályokhoz szükséges – a System.ComponentModel.INotifyPropertyChanged implementálása. Ez a megközelítés magában foglalja egyetlen, nevesített esemény implementálását PropertyChanged. A következő kódban egy példa látható a HostViewModel használatára.

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

    public event PropertyChangedEventHandler PropertyChanged = delegate { };

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

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

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        // Raise the PropertyChanged event, passing the name of the property whose value has changed.
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Most a NextButtonText tulajdonság megfigyelhető. Ha egyirányú vagy kétirányú kötést hoz létre a tulajdonsághoz (a későbbiekben bemutatjuk, hogyan), az eredményként kapott kötési objektum előfizet az PropertyChanged eseményre. Az esemény felmerülésekor a kötésobjektum kezelője egy argumentumot kap, amely a módosított tulajdonság nevét tartalmazza. Így tudja a kötési objektum, hogy melyik tulajdonság értékét olvassa újra.

Ahhoz, hogy ne kelljen többször implementálnia a korábban bemutatott mintát, ha C#-ot használ, a BindableBase (a "Common" mappában) található alaposztályból származtathatja. Íme egy példa arra, hogyan néz ki.

public class HostViewModel : BindableBase
{
    private string nextButtonText;

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

    public string NextButtonText
    {
        get { return nextButtonText; }
        set { SetProperty(ref nextButtonText, value); }
    }
}

Ha az eseményt PropertyChanged a String.Empty argumentummal, vagy a null jelzéssel emelik, ez azt jelzi, hogy az objektum összes nem indexelő tulajdonságát újra kell olvasni. Az eseményt úgy állíthatja be, hogy jelezze, hogy az objektum indexelői tulajdonságai módosultak az adott indexelőkhöz tartozó "Item[indexer]" argumentummal (ahol az indexelő az indexelő értéke), vagy az összes indexelőhöz tartozó "Item[]" értékkel.

A kötésforrásokat egyetlen objektumként, amelynek tulajdonságai adatokat tartalmaznak, vagy objektumgyűjteményként is kezelheti. A C#-kódban egy olyan objektumhoz köthet egyszeri kötést, amely a T< listát> implementálja, így futtatáskor nem változó gyűjteményt jeleníthet meg. Megfigyelhető gyűjtemény esetén (ahol megfigyelhető, hogy az elemeket hozzáadnak vagy eltávolítanak a gyűjteményből), inkább egyirányú adatkapcsolatot hozzunk létre az ObservableCollection<T>-hez. A saját gyűjteményosztályokhoz való kötéshez használja az alábbi táblázatban található útmutatást.

Scenario C# (CLR) C++/WinRT
Kötés egy objektumhoz. Bármilyen objektum lehet. Bármilyen objektum lehet.
Tulajdonságmódosítási értesítések lekérése kötött objektumból. Az objektumnak implementálnia kell az INotifyPropertyChanged parancsot. Az objektumnak implementálnia kell az INotifyPropertyChanged parancsot.
Kötés gyűjteményhez. T lista<> IInspectable IVector vagy IBindableObservableVector. Lásd : XAML-elemek vezérlői; kötés C++/WinRT-gyűjteményhez és gyűjteményekhez C++/WinRT használatával.
Gyűjteménymódosítási értesítések lekérése egy kötött gyűjteményből. ObservableCollection<T> Az IObservableVectorIInspectable típusú. Például winrt::single_threaded_observable_vector<T>.
Implementáljon egy kötést támogató gyűjteményt. A List<T> kiterjesztése vagy IList, IList<Objektum>, IEnumerable vagy IEnumerable<Objektum> implementálása. A IList<T> és a IEnumerable<T> generikushoz való kötés nem támogatott. Implementálja az IVectorIInspectable-t. Lásd : XAML-elemek vezérlői; kötés C++/WinRT-gyűjteményhez és gyűjteményekhez C++/WinRT használatával.
Olyan gyűjtemény implementálása, amely támogatja a gyűjteménymódosítási értesítéseket. Terjessze ki az ObservableCollection<T>-t vagy valósítsa meg a (nem általános) IList és INotifyCollectionChanged-t. Az IInspectableIObservableVector vagy IBindableObservableVector implementálása.
Implementáljon egy gyűjteményt, amely támogatja a növekményes betöltést. Kiterjessze az ObservableCollection<T>-t, vagy implementálja a (nem generikus) IList és INotifyCollectionChanged interfészeket. Emellett implementálja az ISupportIncrementalLoadinget is. Az IInspectableIObservableVector vagy IBindableObservableVector implementálása. Ezenkívül implementálja az ISupportIncrementalLoading

A listavezérlőket tetszőlegesen nagy adatforrásokhoz kötheti, és növekményes betöltéssel továbbra is magas teljesítményt érhet el. A listavezérlőket például anélkül kötheti a Bing-rendszerkép-lekérdezés eredményeihez, hogy egyszerre kellene betöltenie az összes találatot. Ehelyett csak néhány találatot tölt be azonnal, és szükség szerint további eredményeket tölt be. A növekményes betöltés támogatásához az ISupportIncrementalLoading-t olyan adatforráson kell implementálnia, amely támogatja a gyűjteménymódosítási értesítéseket. Amikor az adatkötési motor több adatot kér, az adatforrásnak meg kell adnia a megfelelő kéréseket, integrálnia kell az eredményeket, majd el kell küldenie a megfelelő értesítéseket a felhasználói felület frissítéséhez.

Kötési cél

Az alábbi két példában a Button.Content tulajdonság a kötési cél. Értéke egy korrektúrakiterjesztésre van állítva, amely deklarálja a kötési objektumot. Az első példában {x:Bind}, a másodikban pedig a {Binding} látható. A kötések jelölőnyelvben való deklarálása általános eset, mert kényelmes, olvasható és jól kezelhető. Ha azonban szükséges, elkerülheti a korrektúrát, és imperatív módon (programozott módon) létrehozhatja a Kötés osztály egy példányát.

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

Ha C++/WinRT-t használ, akkor hozzá kell adnia a BindableAttribute attribútumot minden olyan futtatókörnyezeti osztályhoz, amellyel a {Binding} korrektúrakiterjesztést használni szeretné.

Fontos

C++/WinRT használata esetén a BindableAttribute attribútum elérhető a Windows App SDK-val. Ezen attribútum nélkül implementálnia kell az ICustomPropertyProvider és az ICustomProperty interfészeket a {Binding} korrektúrabővítmény használatához.

{x:Bind} használatával deklarált kötési objektum

A {x:Bind} korrektúra létrehozása előtt el kellérhetővé tennie a kötés forrásosztályát a korrektúraoldalt képviselő osztályból. Adjon hozzá egy (ebben az esetben ilyen típusú HostViewModel ) tulajdonságot az MainWindow ablakosztályhoz.

namespace DataBindingInDepth
{
    public sealed partial class MainWindow : Window
    {
        public MainWindow()
        {
            this.InitializeComponent();
            ViewModel = new HostViewModel();
        }
    
        public HostViewModel ViewModel { get; set; }
    }
}

A tulajdonság hozzáadása után részletesebben is áttekintheti a kötési objektumot deklaráló jelölést. Az alábbi példa ugyanazt Button.Content a kötési célt használja, amelyet korábban a "Kötési cél" szakaszban látott. Megjeleníti a célt, amely a HostViewModel.NextButtonText tulajdonsághoz van kötve.

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

Figyelje meg a megadott Pathértéket. Az ablak ezt az értéket a saját kontextusában értelmezi. Ebben az esetben az elérési út azzal kezdődik, hogy az imént hozzáadott ViewModel tulajdonságra hivatkozunk a MainWindow oldalon. Ez a tulajdonság egy HostViewModel példányt ad vissza, így az objektum pont jelöléssel való elérésével elérheti a HostViewModel.NextButtonText tulajdonságot. Megadhatja Mode , hogy felülbírálja az egyszeri {x:Bind} alapértelmezett értékét.

Az Elérési út tulajdonság számos szintaxisbeállítást támogat a beágyazott tulajdonságokhoz, a csatolt tulajdonságokhoz, valamint az egész számhoz és a sztringindexelőkhöz való kötéshez. További információ: Tulajdonság-elérési út szintaxisa. A sztringindexelőkhöz való kötés az ICustomPropertyProvider implementálása nélkül teszi lehetővé a dinamikus tulajdonságokhoz való kötést. További beállítások: {x:Bind} korrektúrakiterjesztés.

Annak szemléltetéséhez, hogy a HostViewModel.NextButtonText tulajdonság megfigyelhető, adjon hozzá egy eseménykezelőt Click a gombhoz, és frissítse a tulajdonság értékét HostViewModel.NextButtonText. Buildelje, futtassa, majd kattintson a gombra a gomb Content frissítésének értékének megtekintéséhez.

// MainWindow.xaml.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
    ViewModel.NextButtonText = "Updated Next button text";
}

Megjegyzés:

A TextBox.Text módosításait a rendszer kétirányú kötött forrásba küldi, amikor a Szövegdoboz elveszíti a fókuszt, és nem minden felhasználói billentyűleütés után.

DataTemplate és x:DataType

A DataTemplate-ban (függetlenül attól, hogy elemsablonként, tartalomsablonként vagy fejlécsablonként használja) a rendszer nem értelmezi az értékeket Path az ablak kontextusában. Ehelyett az adatobjektum sablonozási kontextusában működik. Amikor az {x:Bind} elemet használja egy adatsablonban, ellenőrizheti annak kötéseit fordítási időben, és hatékony kódot generálhat ezekhez. Ehhez a DataTemplate-nak deklarálnia kell az adatobjektum típusát a x:DataType használatával. Az alábbi példa felhasználható elemvezérlőként, amely ItemTemplate kapcsolódik egy SampleDataGroup objektumgyűjteményhez.

<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>

Gyengén gépelt objektumok az elérési úton

Tegyük fel, hogy van egy megnevezett SampleDataGroup típus, amely egy string tulajdonságot implementál, Title. Egy olyan tulajdonsága MainWindow.SampleDataGroupAsObject is van, amelynek a típusa object, de valójában egy SampleDataGroup példányt ad vissza. A kötés <TextBlock Text="{x:Bind SampleDataGroupAsObject.Title}"/> fordítási hibát eredményez, mert a Title tulajdonság nem található a típuson object. A hiba kijavításához adjon hozzá egy öntöttet a Path szintaxishoz a következő módon: <TextBlock Text="{x:Bind ((data:SampleDataGroup)SampleDataGroupAsObject).Title}"/>. Íme egy másik példa, ahol Element deklarálva object van, de valójában TextBlock: <TextBlock Text="{x:Bind Element.Text}"/>. A cast kijavítja a problémát: <TextBlock Text="{x:Bind ((TextBlock)Element).Text}"/>.

Ha az adatok aszinkron módon töltődik be

A windows részleges osztályai fordítási időben kódot generálnak az {x:Bind} támogatására. Ezeket a fájlokat megtalálhatja a obj mappában, például (c#) <view name>.g.csnéven. A létrehozott kód tartalmaz egy kezelőt az ablak betöltési eseményéhez. Ez a kezelő meghívja a Initialize metódust egy generált osztályon, amely az ablak kötéseit jelöli. A Initialize a Update hívással kezdi az adatok mozgatását a kötési forrás és a cél között. Loading az ablak vagy a felhasználói vezérlő első mértéke előtt történik. Ha az adatok aszinkron módon tölthetők be, előfordulhat, hogy a hívás idejére Initialize nem lesznek készen. Az adatok betöltése után kényszerítheti az egyszeri kötések inicializálását hívással this.Bindings.Update();. Ha csak egyszeri kötésekre van szüksége az aszinkron módon betöltött adatokhoz, sokkal olcsóbb inicializálni őket, mint egyirányú kötéseket használni, és figyelni a módosításokat. Ha az adatok nem mennek át részletes módosításokon, és valószínűleg egy adott művelet részeként frissülnek, a kötéseket egyszeri alkalommal is végrehajthatja, és bármikor kényszerítheti a manuális frissítést egy hívással Update.

Megjegyzés:

{x:Bind} nem alkalmas késői kötött forgatókönyvekre, például egy JSON-objektum szótárszerkezetének navigálására vagy a kacsagépelésre. A "kacsagépelés" a tulajdonságnevek lexikális egyezései alapján történő gépelés gyenge formája (ahogy a "ha sétál, úszik és reng, mint egy kacsa, akkor ez egy kacsa"). Kacsagépelés esetén a Age tulajdonsághoz való kötés egyformán megfelelne egy Person vagy egy Wine objektumnak (feltéve, hogy mindegyik típus rendelkezik tulajdonsággal Age ). Ezekben a forgatókönyvekben használja a {Binding} korrektúrabővítményt.

A(z) {Binding} használatával deklarált kötési objektum

C++/WinRT használata esetén adja hozzá a BindableAttribute attribútumot minden olyan futtatókörnyezeti osztályhoz, amelyhez a {Binding} jelölőbővítmény használatakor csatlakozni szeretne. A(z) {x:Bind} használatához nincs szükség erre az attribútumra.

// HostViewModel.idl
// Add this attribute:
[Microsoft.UI.Xaml.Data.Bindable]
runtimeclass HostViewModel : Microsoft.UI.Xaml.Data.INotifyPropertyChanged
{
    HostViewModel();
    String NextButtonText;
}

Fontos

C++/WinRT használata esetén a BindableAttribute attribútum elérhető a Windows App SDK-val. Ezen attribútum nélkül implementálnia kell az ICustomPropertyProvider és az ICustomProperty interfészeket a {Binding} korrektúrabővítmény használatához.

Alapértelmezés szerint a {Binding} feltételezi, hogy a korrektúraablak DataContext eleméhez van kötés. Állítsa be az DataContext ablakot a kötés forrásosztályának egy példányára (amely HostViewModel típusú ebben az esetben). Az alábbi példa azt jelöli, hogyan deklarálható a kötés objektum. Ugyanazt Button.Content a kötési célt használja, amelyet korábban a "Kötési cél" szakaszban használt, és a HostViewModel.NextButtonText tulajdonsághoz kapcsolódik.

<Window xmlns:viewmodel="using:DataBindingInDepth" ... >
    <Window.DataContext>
        <viewmodel:HostViewModel x:Name="viewModelInDataContext"/>
    </Window.DataContext>
    ...
    <Button Content="{Binding Path=NextButtonText}" ... />
</Window>
// MainWindow.xaml.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
    viewModelInDataContext.NextButtonText = "Updated Next button text";
}

Figyelje meg a megadott Pathértéket. Az ablak DataContextje értelmezi ezt az értéket, amely ebben a példában egy HostViewModel példányra van beállítva. Az elérési út a tulajdonságra HostViewModel.NextButtonText hivatkozik. Az Mode kihagyható, mert itt az {Binding} alapértelmezett egyirányú kötése megfelelően működik.

A felhasználói felületi elem DataContextjének alapértelmezett értéke a szülő öröklött értéke. Ezt az alapértelmezett beállítást DataContext explicit módon felülbírálhatja, amelyet a gyermekek alapértelmezés szerint örökölnek. Az elemek explicit beállítása DataContext akkor hasznos, ha több olyan kötést szeretne használni, amelyek ugyanazt a forrást használják.

A kötésobjektumok tulajdonsága Source alapértelmezés szerint annak a felhasználói felületi elemnek a DataContextje , amelyen a kötés deklarálva van. Ezt az alapértelmezett értéket felülbírálhatja a kötés beállításával SourceRelativeSourcevagy ElementName explicit módon (a részletekért lásd: {Binding} ).

Egy DataTemplate-fájlon belül a DataContext automatikusan a sablonozott adatobjektumra van állítva. Az alábbi példa a ItemTemplate szerepét töltheti be egy tetszőleges típusú gyűjteményhez kötött vezérlőelem számára, amely sztringtulajdonságként Title és Description nevet visel.

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

Megjegyzés:

Alapértelmezés szerint a TextBox.Text módosításai kétirányú kötött forrásba kerülnek, amikor a Szövegdoboz elveszíti a fókuszt. Ha azt szeretné, hogy a módosítások minden felhasználói billentyűleütés után el legyenek küldve, állítsa UpdateSourceTriggerPropertyChanged be a kötésre a korrektúrában. Azt is teljes mértékben szabályozhatja, hogy a rendszer mikor küld módosításokat a forrásnak UpdateSourceTriggera következő beállítássalExplicit: . Ezután kezelheti a szövegmező eseményeit (általában TextBox.TextChanged), meghívja a GetBindingExpression parancsot a célon egy BindingExpression objektum lekéréséhez, végül meghívja a BindingExpression.UpdateSource parancsot az adatforrás programozott frissítéséhez.

Az Elérési út tulajdonság számos szintaxisbeállítást támogat a beágyazott tulajdonságokhoz, a csatolt tulajdonságokhoz, valamint az egész számhoz és a sztringindexelőkhöz való kötéshez. További információ: Tulajdonság-elérési út szintaxisa. A sztringindexelőkhöz való kötés az ICustomPropertyProvider implementálása nélkül teszi lehetővé a dinamikus tulajdonságokhoz való kötést. Az ElementName tulajdonság elemről elemre kötés esetén hasznos. A RelativeSource tulajdonságnak több felhasználási módja is van, amelyek közül az egyik a ControlTemplate-on belüli sablonkötés hatékonyabb alternatívája. További beállításokért tekintse meg a {Binding} korrektúrabővítményt és a Kötés osztályt.

Mi történik, ha a forrás és a cél nem azonos típusú?

Ha egy felhasználói felületi elem láthatóságát egy logikai tulajdonság értéke alapján szeretné szabályozni, vagy ha egy numerikus érték tartományának vagy trendjének függvényét képező színnel szeretne megjeleníteni egy felhasználói felületi elemet, vagy ha egy dátum- és/vagy időértéket szeretne megjeleníteni egy olyan felhasználói felületi elemtulajdonságban, amely sztringre számít, ezután át kell alakítania az értékeket egyik típusból a másikba. Vannak olyan esetek, amikor a megfelelő megoldás az, ha a kötési forrásosztályból egy másik, a megfelelő típusú tulajdonságot tesz elérhetővé, és a konverziós logikát itt foglalja magában és tesztelheti. Ez a megoldás azonban nem rugalmas vagy méretezhető, ha sok vagy nagy kombinációjú forrás- és céltulajdonsággal rendelkezik. Ebben az esetben több lehetősége is van:

  • Ha ezt használja {x:Bind} , közvetlenül egy függvényhez kötheti az átalakítást
  • Vagy megadhat egy értékkonvertert, amely az átalakítás végrehajtására tervezett objektum

Értékkonverterek

Az alábbi értékkonverter alkalmas egy egyszeri vagy egyirányú kötésre, amely egy DateTime-értéket egy hónapot tartalmazó értékké string alakít át. Az osztály implementálja az IValueConvertert.

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();
    }
}

Ezt az értékkonvertert pedig így használhatja fel a kötésobjektum-jelölőben.

<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}}"/>

A kötési motor meghívja a Konvertálás és a ConvertBack metódust, ha a Kötés konverter paramétere definiálva van. Amikor adatokat ad át a forrásból, a kötési motor meghívja Convert és átadja a visszaadott adatokat a célnak. Amikor adatokat ad át a céltól (kétirányú kötés esetén), a kötési motor meghívja ConvertBack és átadja a visszaadott adatokat a forrásnak.

A konverter opcionális paraméterekkel is rendelkezik: ConverterLanguage, amely lehetővé teszi az átalakításban használni kívánt nyelv megadását, és a ConverterParameter, amely lehetővé teszi a konverziós logika paraméterének átadását. Konverterparamétert használó példa: IValueConverter.

Megjegyzés:

Ha hiba történt az átalakítás során, ne tegyen kivételt. Ehelyett adja vissza a DependencyProperty.UnsetValue értéket, amely leállítja az adatátvitelt.

Ha egy alapértelmezett értéket szeretne megjeleníteni, amelyet akkor kell használni, amikor a kötési forrás nem oldható fel, állítsa be a FallbackValue tulajdonságot a kötésobjektumon a korrektúrában. Ez hasznos a konvertálási és formázási hibák kezeléséhez. Hasznos olyan forrástulajdonságokhoz is kötni, amelyek nem feltétlenül léteznek a heterogén típusú kötött gyűjtemény összes objektumán.

Ha egy szövegvezérlőt olyan értékhez köt, amely nem sztring, az adatkötési motor sztringgé alakítja az értéket. Ha az érték hivatkozástípus, az adatkötési motor lekéri a sztringértéket az ICustomPropertyProvider.GetStringRepresentation vagy az IStringable.ToString hívásával, ha elérhető, és más módon meghívja az Object.ToString parancsot. Vegye figyelembe azonban, hogy a kötési motor figyelmen kívül hagyja ToString az alaposztályú implementációt elrejtő implementációkat. Az alosztály implementációinak felül kell bírálnia az alaposztály ToString metódusát. Hasonlóképpen, az natív nyelvekben az összes felügyelt objektum az ICustomPropertyProvider és az IStringable implementálásához tűnik. Azonban a metódusra GetStringRepresentation irányuló és IStringable.ToString az ahhoz Object.ToString irányított hívások, illetve a metódus felülbírálása soha nem kerül olyan új ToString implementációba, amely elrejti az alaposztályú implementációt.

Megjegyzés:

A Windows Community Toolkit egy BoolToVisibilityConvertert biztosít. A konverter true megfelel az Visible enumerálási értéknekfalse, és Collapsed így konverter létrehozása nélkül is köthet egy Visibility tulajdonságot egy logikai értékhez. A konverter használatához a projektnek hozzá kell adnia a CommunityToolkit.WinUI.Converters NuGet csomagot.

Függvénykötés a következőben: {x:Bind}

{x:Bind} lehetővé teszi, hogy a kötési útvonal utolsó lépése függvény legyen. Ezzel a funkcióval konverziókat hajthat végre, vagy több tulajdonságtól függő kötéseket hozhat létre. További információ: Functions in x:Bind.

Elem–elem kötés

Egy XAML-elem tulajdonságát egy másik XAML-elem tulajdonságához kötheti. Íme egy példa a kötés korrektúrában való megjelenésére.

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

Erőforrás-szótárak a következővel: {x:Bind}

A(z) {x:Bind} jelölőbővítmény a kódgenerálástól függ, ezért szüksége van egy kód mögötti fájlra, amely egy konstruktort tartalmaz, amely meghívja InitializeComponent (a generált kód inicializálásához). Az erőforrás szótárának újrafelhasználásához a fájlnévre való hivatkozás helyett példányosíthatja annak típusát (így InitializeComponent hívják). Íme egy példa arra, hogy mi a teendő, ha rendelkezik egy meglévő erőforrás-szótárval, és használni {x:Bind} szeretné azt.

<!-- 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 Microsoft.UI.Xaml.Data;
 
namespace ExampleNamespace
{
    public partial class TemplatesResourceDictionary
    {
        public TemplatesResourceDictionary()
        {
            InitializeComponent();
        }
    }
}
<!-- MainWindow.xaml -->
<Window x:Class="ExampleNamespace.MainWindow"
    ....
    xmlns:examplenamespace="using:ExampleNamespace">

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

{x:Bind} és {Binding} keverése újrafelhasználható stílusban

Az előző példa bemutatta, hogyan használható {x:Bind} a DataTemplatesben. Olyan újrafelhasználható stílusokat is létrehozhat, amelyek egyesítik mind a {x:Bind} mind a {Binding} jelölő kiterjesztéseket. Ez a kombináció akkor hasznos, ha egyes tulajdonságokat fordítás idejéhez ismert értékekhez szeretne kötni a {x:Bind} használatával, és más tulajdonságokat a futásidejű adatkontextus értékekhez a {Binding} használatával.

Az alábbi példa bemutatja, hogyan hozhat létre olyan újrafelhasználható gombstílust, amely mindkét kötési módszert használja:

TemplatesResourceDictionary.xaml

<!-- 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

// TemplatesResourceDictionary.xaml.cs
using Microsoft.UI;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Data;
using Microsoft.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);
    }
}

A MainWindow.xaml használata futtatókörnyezeti értékeket biztosító ViewModellel:

<!-- MainWindow.xaml -->
<Window x:Class="ExampleNamespace.MainWindow"
    ....
    xmlns:examplenamespace="using:ExampleNamespace">

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

    <Grid>
        <Grid.DataContext>
            <examplenamespace:ButtonThemeViewModel/>
        </Grid.DataContext>
        
        <StackPanel Margin="20">
            <!-- These buttons use the mixed binding style -->
            <Button Content="Save" Style="{StaticResource CustomButtonStyle}"/>
            <Button Content="Cancel" Style="{StaticResource CustomButtonStyle}"/>
        </StackPanel>
    </Grid>
</Window>

ButtonThemeViewModel.cs (a futtatókörnyezeti kötési értékeket biztosító DataContext):

using System.ComponentModel;
using Microsoft.UI;
using Microsoft.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;
    }
}

Ebben a példában:

  • {Binding} a DataContexttől függő tulajdonságokhoz használható (ButtonBackgroundBrush, ButtonForegroundBrush, ButtonHoverBrush)
  • {x:Bind} olyan tulajdonságokhoz használatos, amelyek fordítási ideje ismert, és maga a ResourceDictionary része (DefaultIndicatorBrush, DefaultPressedBrush)
  • A stílus újrafelhasználható, és bármelyik gombra alkalmazhatja
  • A futásidejű készítés a DataContext használatával lehetséges, miközben a statikus elemek teljesítménye {x:Bind} továbbra is előnyös

Eseménykötés és ICommand

A(z) {x:Bind} támogatja az eseménykötés nevű funkciót. Ezzel a funkcióval megadhatja egy esemény kezelőjét egy kötés használatával. Ez a funkció egy további lehetőség az események kezelésére, azon felül, hogy az eseményeket egy metódussal kezeli a kód mögötti fájlban. Tegyük fel, hogy van egy ListViewDoubleTapped eseménykezelője az MainWindow osztályban.

public sealed partial class MainWindow : Window
{
    ...
    public void ListViewDoubleTapped()
    {
        // Handle double-tapped logic
    }
}

A ListView DoubleTapped eseményét a MainWindow egyik metódusához kötheti, mint ez.

<ListView DoubleTapped="{x:Bind ListViewDoubleTapped}" />

Ezzel a technikával nem lehet túlterhelt metódusokkal kezelni egy eseményt. Ha az eseményt kezelő metódus paraméterekkel is rendelkezik, akkor mindegyiknek hozzárendelhetőnek kell lennie az esemény összes paraméterének típusából. Ebben az esetben nincs túlterhelve, ListViewDoubleTapped és nincsenek paraméterei (de akkor is érvényes lenne, ha két object paramétert vett volna igénybe).

Az eseménykötési technika hasonló a parancsok implementálásához és használatához. A parancsok olyan tulajdonságok, amelyek egy olyan objektumot adnak vissza, amely megvalósítja az ICommand felületet. A (z) {x:Bind} és a {Binding} egyaránt parancsokkal dolgozik. Ahhoz, hogy ne kelljen többször implementálnia a parancsmintát, használhatja a DelegateCommandQuizGame UWP-mintában található segédosztályt (a "Common" mappában).

Kötés mappák vagy fájlok gyűjteményéhez

A Windows.Storage névtér api-jait használhatja a csomagolt Windows App SDK-alkalmazások mappáinak és fájladatainak lekéréséhez. A különböző GetFilesAsync, GetFoldersAsyncés GetItemsAsync metódusok azonban nem a vezérlőelemek kötésére alkalmas értékeket adnak vissza. Ehelyett a FileInformationFactory osztály GetVirtualizedFilesVector, GetVirtualizedFoldersVector és GetVirtualizedItemsVector metódusainak visszatérési értékeihez kell kapcsolódnia. A StorageDataSource és a GetVirtualizedFilesVector UWP minta alábbi kódpéldája a tipikus használati mintát mutatja. Ne felejtse el deklarálni a picturesLibrary képességet az alkalmazáscsomag-jegyzékben, és győződjön meg arról, hogy vannak képek a Képek tár mappájában.

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;
}

Ezt a módszert általában arra használja, hogy írásvédett nézetet hozzon létre a fájl- és mappainformációkról. Létrehozhat kétirányú kötéseket a fájl- és mappatulajdonságokhoz, például lehetővé teheti, hogy a felhasználók zenenézetben értékeljenek egy dalt. A módosítások azonban nem maradnak meg, amíg meg nem hívja a megfelelő SavePropertiesAsync metódust (például MusicProperties.SavePropertiesAsync). Akkor kell véglegesítenie a módosításokat, ha az elem elveszíti a fókuszt, mert ez a művelet a kijelölés alaphelyzetbe állítását váltja ki.

Vegye figyelembe, hogy az ezzel a technikával végzett kétirányú kötés csak indexelt helyeken működik, például a Zene szolgáltatással. A FolderInformation.GetIndexedStateAsync metódus meghívásával meghatározhatja, hogy egy hely indexelve van-e.

Vegye figyelembe azt is, hogy a virtualizált vektorok vissza tudnak térni null néhány elemhez, mielőtt feltöltené az értéküket. Például egy virtualizált vektorhoz kötött listavezérlő null értékének használata előtt érdemes ellenőriznie, vagy inkább a SelectedIndexet kell használnia.

Kötés kulcs szerint csoportosított adatokhoz

Ha egy elemcsoportot (például egy osztály által BookSku képviselt könyveket) vesz fel, és az elemeket kulcsként egy közös tulajdonság (például a BookSku.AuthorName tulajdonság) használatával csoportosítja, akkor az eredményt csoportosított adatoknak nevezzük. Ha csoportosítja az adatokat, az már nem egy egybesimított gyűjtemény. A csoportosított adatok csoportobjektumok gyűjteményei, ahol minden csoportobjektum a következőkkel rendelkezik:

  • kulcs, és
  • olyan elemek gyűjteménye, amelyek tulajdonsága megegyezik a kulcssal.

Ha ismét meg szeretné venni a könyvek példáját, a könyvek szerzőnév szerinti csoportosításának eredménye egy szerzői névcsoportok gyűjteményét eredményezi, ahol az egyes csoportok a következővel rendelkezik:

  • egy kulcs, amely egy szerző neve, és
  • azoknak az objektumoknak a BookSku gyűjteménye, amelyek AuthorName tulajdonsága megegyezik a csoport kulcsával.

A gyűjtemények megjelenítéséhez általában közvetlenül egy gyűjteményt visszaadó tulajdonsághoz köti egy elemvezérlő ItemsSource elemforrását (például ListView vagy GridView). Ha ez egy egyszerű gyűjtemény, akkor nem kell semmi különlegeset tennie. Ha azonban csoportobjektum-gyűjteményről van szó (mint a csoportosított adatokhoz való kötéskor), akkor szüksége lesz egy CollectionViewSource nevű közbenső objektum szolgáltatásaira, amely az elemek vezérlője és a kötési forrás között helyezkedik el. A csoportosított adatokat visszaadó tulajdonsághoz köti CollectionViewSource a tulajdonságot, és az elemek vezérlőelemet a CollectionViewSource. Egy további érték hozzáadása CollectionViewSource az, hogy nyomon követi az aktuális elemet, így több elem vezérlését is szinkronizálhatja úgy, hogy mindet egyhez CollectionViewSourceköti. Az aktuális elemet programozott módon is elérheti a CollectionViewSource.View tulajdonság által visszaadott objektum ICollectionView.CurrentItem tulajdonságán keresztül.

A CollectionViewSource csoportosítási létesítményének aktiválásához állítsa az IsSourceGroupedtrueértéket . Az, hogy az ItemsPath tulajdonságot is be kell-e állítania, pontosan attól függ, hogyan kell létrehoznia a csoportobjektumokat. A csoportobjektumok készítésének két módja van: az "is-a-group" minta és a "has-a-group" minta. Az "is-a-group" mintában a csoportobjektum gyűjteménytípusból származik (például List<T>), így a csoportobjektum valójában maga az elemek csoportja. Ezzel a mintával nem kell beállítania ItemsPath. A "has-a-group" mintában a csoportobjektum egy vagy több gyűjteménytípusú tulajdonsággal rendelkezik (például List<T>), így a csoport "egy" elemcsoporttal rendelkezik egy tulajdonság formájában (vagy több elemcsoportban több tulajdonság formájában). Ezzel a mintával az elemek csoportját tartalmazó tulajdonság nevére kell állítania ItemsPath .

Az alábbi példa a "van-egy-csoportja" mintát szemlélteti. Az ablakosztálynak van egy DataContext nevű tulajdonsága, amely a nézetmodell egy példányát adja vissza. A CollectionViewSource a Authors nézetmodell tulajdonságához (Authors a csoportobjektumok gyűjteményéhez) kapcsolódik, és azt is megadja, hogy a Author.BookSkus csoportosított elemeket tartalmazó tulajdonság. Végül a GridView a csoportstílushoz CollectionViewSourcevan kötve, és úgy van definiálva, hogy a csoportok elemeit megjeleníthesse.

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

Az "is-a-group" mintát kétféleképpen valósíthatja meg. Ennek egyik módja a saját csoportosztály létrehozása. Származtathatja az osztályt List<T> (ahol T az elemek típusa). Például: public class Author : List<BookSku>. A második módszer egy LINQ-kifejezés használata csoportobjektumok (és csoportosztályok) dinamikus létrehozásához a BookSku-elemek hasonló tulajdonságértékeiből. Ez a megközelítés – ha csak egy egyszerű lista áll fenn az elemek között, és menet közben csoportosítja őket – jellemzően egy olyan alkalmazás, amely egy felhőszolgáltatásból fér hozzá az adatokhoz. Rugalmasan csoportosíthatja a könyveket szerző vagy műfaj szerint (például) anélkül, hogy speciális csoportosztályokra, például a Szerzőre és a Műfajra lenne szüksége.

Az alábbi példa a LINQ használatával szemlélteti az "is-a-group" mintát. Ezúttal műfaj szerint csoportosítjuk a könyveket, és a csoportfejlécekben a műfaj neve látható. Ezt a csoportosítást a "Kulcs" tulajdonság elérési útja jelzi a csoportkulcs értékére hivatkozva.

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

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

Ne feledje, hogy a(z) {x:Bind} adatsablonokkal való használatakor egy érték beállításával x:DataType meg kell jelölnie, hogy milyen típushoz van kötve. Ha a típus általános, akkor ezt nem fejezheti ki korrektúraként, ezért a csoportstílus fejlécsablonjában a {Binding} kifejezést kell használnia.

    <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>

A SzemanticZoom vezérlő nagyszerű lehetőséget biztosít a felhasználók számára a csoportosított adatok megtekintésére és navigálására. A Bookstore2 UWP mintaalkalmazás bemutatja, hogyan használható a SemanticZoom. Ebben az alkalmazásban megtekintheti a szerzők szerint csoportosított könyvek listáját (a nagyított nézetet), vagy kicsinyítheti is a szerzők jumplistáját (a kicsinyített nézetet). A jump lista sokkal gyorsabb navigációt biztosít, mint a könyvek listájának görgetése. A nagyított és kicsinyített nézetek valójában ListView vagy GridView ugyanahhoz CollectionViewSourcea vezérlőhöz vannak kötve.

SzemanticZoom illusztrációja

Ha hierarchikus adatokhoz – például kategóriákon belüli alkategóriákhoz – kapcsolódik, a felhasználói felületen több elemvezérlővel is megjelenítheti a hierarchikus szinteket. Az egyik elem vezérlőelemben lévő kijelölés határozza meg a további elemvezérlők tartalmát. A listákat szinkronizálhatja úgy, hogy az egyes listákat a saját CollectionViewSource-hoz köti, és egy láncban köti össze a CollectionViewSource példányokat. Ezt a beállítást master/details (vagy list/details) nézetnek nevezzük. További információ : Hierarchikus adatokhoz való kötés és master/details nézet létrehozása.

Adatkötési problémák diagnosztizálása és hibakeresése

A kötési korrektúra tartalmazza a tulajdonságok nevét (c# esetén pedig néha mezőket és metódusokat). Ezért amikor átnevez egy tulajdonságot, módosítania kell az arra hivatkozó kötéseket is. Ha elfelejti ezt megtenni, adatkötési hibát hoz létre, és az alkalmazás vagy nem fordít le, vagy nem fut megfelelően.

A(z) {x:Bind} és {Binding} által létrehozott kötésobjektumok funkcionálisan egyenértékűek. De {x:Bind} rendelkezik a kötési forrás típusadataival, és fordításkor hozza létre a forráskódot. {x:Bind} használatával ugyanazt a fajta problémaészlelést kapja, mint amit a kód többi részénél tapasztal. Ez az észlelés magában foglalja a kötési kifejezések fordítási idejének ellenőrzését és a hibakeresést a forráskódban a lap részleges osztályaként létrehozott töréspontok beállításával. Ezeket az osztályokat a obj mappában található fájlokban találja meg, olyan nevekkel, mint például (C#) <view name>.g.cs. Ha probléma merült fel egy kötéssel kapcsolatban, kapcsolja be a Nem kezelt kivételek megszakítása funkciót a Microsoft Visual Studio hibakeresőjében. A hibakereső ezen a ponton megszakítja a végrehajtást, és ekkor megvizsgálhatja, mi ment rosszul. A létrehozott {x:Bind} kód ugyanazt a mintát követi a kötési forráscsomópontok gráfjának minden részén, és a Hívásverem ablakban található információk segítségével meghatározhatja a problémához vezető hívások sorozatát.

A(z) {Binding} nem rendelkezik a kötés forrásának típusadataival. Ha azonban az alkalmazást a hibakeresővel együtt futtatja, a kötési hibák megjelennek a Visual Studio Kimenet és XAML kötési hibái ablakában. A Visual Studióban a kötési hibák hibakereséséről további információt az XAML adatkötési diagnosztikában talál.

Kötések létrehozása kódban

Megjegyzés:

Ez a szakasz csak a(z) {Binding}-ra vonatkozik, mert nem hozhat létre {x:Bind} kötéseket a kódban. A {x:Bind} szolgáltatással azonban ugyanezeket az előnyöket érheti el, így bármilyen függőségi tulajdonságon regisztrálhat változásértesítéseket.

A felhasználói felület elemeit XAML helyett eljárási kóddal is csatlakoztathatja az adatokhoz. Ehhez hozzon létre egy új kötésobjektumot , állítsa be a megfelelő tulajdonságokat, majd hívja meg a FrameworkElement.SetBinding vagy a BindingOperations.SetBinding parancsot. A kötések programozott létrehozása akkor hasznos, ha futásidőben szeretné kiválasztani a kötéstulajdonság-értékeket, vagy egyetlen kötést szeretne megosztani több vezérlő között. A hívás után azonban nem módosíthatja a kötési tulajdonság értékeit SetBinding.

Az alábbi példa bemutatja, hogyan implementálhat egy kötést a kódban.

<TextBox x:Name="MyTextBox" Text="Text"/>
// Create an instance of the MyColors class 
// that implements INotifyPropertyChanged.
var 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.
var binding = new Binding { Path = new PropertyPath("Brush1") };
MyTextBox.SetBinding(TextBox.ForegroundProperty, binding);

{x:Bind} és {Binding} funkció összehasonlítása

Tulajdonság {x:Bind} és {Binding} Jegyzetek
Az elérési út az alapértelmezett tulajdonság {x:Bind a.b.c}
-
{Binding a.b.c}
Elérési út tulajdonság {x:Bind Path=a.b.c}
-
{Binding Path=a.b.c}
x:Bind Alapértelmezés Pathszerint az ablakban gyökerezik, nem a DataContextben.
Indexelő {x:Bind Groups[2].Title}
-
{Binding Groups[2].Title}
Kötések a gyűjtemény megadott eleméhez. Csak egész számalapú indexek támogatottak.
Csatolt tulajdonságok {x:Bind Button22.(Grid.Row)}
-
{Binding Button22.(Grid.Row)}
A csatolt tulajdonságok zárójelek használatával vannak megadva. Ha a tulajdonság nem XAML-névtérben van deklarálva, előtagként egy XML-névteret kell használnia, amelyet a dokumentum elején lévő kódnévtérhez kell hozzárendelni.
Öntés {x:Bind groups[0].(data:SampleDataGroup.Title)}
-
Nem szükséges a {Binding}.
A leadások zárójelek használatával vannak megadva. Ha a tulajdonság nem XAML-névtérben van deklarálva, előtagként egy XML-névteret kell használnia, amelyet a dokumentum elején lévő kódnévtérhez kell hozzárendelni.
Konverter {x:Bind IsShown, Converter={StaticResource BoolToVisibility}}
-
{Binding IsShown, Converter={StaticResource BoolToVisibility}}
Konvertereket deklarálhat az Ablak, a Vezérlő, a ResourceDictionary vagy az App.xaml gyökérszintjén.
ÁtalakítóParaméter, ÁtalakítóNyelv {x:Bind IsShown, Converter={StaticResource BoolToVisibility}, ConverterParameter=One, ConverterLanguage=fr-fr}
-
{Binding IsShown, Converter={StaticResource BoolToVisibility}, ConverterParameter=One, ConverterLanguage=fr-fr}
Konvertereket deklarálhat az Ablak, a Vezérlő, a ResourceDictionary vagy az App.xaml névterének gyökerén.
TargetNullValue {x:Bind Name, TargetNullValue=0}
-
{Binding Name, TargetNullValue=0}
Akkor használatos, ha a kötési kifejezés levele null. Sztringértékhez használjon egyetlen idézőjelet.
FallbackValue {x:Bind Name, FallbackValue='empty'}
-
{Binding Name, FallbackValue='empty'}
Akkor használatos, ha a kötés elérési útjának bármely része (a levél kivételével) null értékű.
Elemnév {x:Bind slider1.Value}
-
{Binding Value, ElementName=slider1}
{x:Bind} egy mezőhöz van kötve; Path alapértelmezés szerint az ablakhoz van kapcsolva, ezért bármely elnevezett elemet elérhet a mezőjén keresztül.
RelativeSource: Önmagára <Rectangle x:Name="rect1" Width="200" Height="{x:Bind rect1.Width}" ... />
-
<Rectangle Width="200" Height="{Binding Width, RelativeSource={RelativeSource Self}}" ... />
A következővel {x:Bind}nevezze el az elemet, és használja a nevét a következőben Path: .
RelativeSource: TemplatedParent Nincs szükség {x:Bind}
-
{Binding <path>, RelativeSource={RelativeSource TemplatedParent}}
A With (Be{x:Bind}TargetType) ControlTemplate a sablon szülőhöz való kötést jelzi. A {Binding}normál sablonkötés a legtöbb felhasználási célra használható vezérlősablonokban is használható. De használja TemplatedParent azt a lehetőséget, ahol konvertert vagy kétirányú kötést kell használnia.
Forrás Nincs szükség {x:Bind}
-
<ListView ItemsSource="{Binding Orders, Source={StaticResource MyData}}"/>
A {x:Bind} névvel ellátott elem közvetlen használatához használjon tulajdonságot vagy statikus elérési utat.
Üzemmód {x:Bind Name, Mode=OneWay}
-
{Binding Name, Mode=TwoWay}
Mode lehet OneTime, OneWayvagy TwoWay. alapértelmezett érték: ; alapértelmezett érték: .>
UpdateSourceTrigger {x:Bind Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}
-
{Binding UpdateSourceTrigger=PropertyChanged}
UpdateSourceTrigger lehet Default, LostFocusvagy PropertyChanged. {x:Bind} nem támogatja UpdateSourceTrigger=Explicit. {x:Bind} viselkedést használ PropertyChanged minden esetben, kivéve TextBox.Text, ha viselkedést használ LostFocus .

Lásd még