Sdílet prostřednictvím


Hloubková datová vazba Windows

Tento článek popisuje funkce datových vazeb WinUI pomocí rozhraní API v oboru názvů Microsoft.UI.Xaml.Data.

Poznámka:

Toto téma podrobně popisuje funkce datových vazeb. Stručný praktický úvod najdete v přehledu datových vazeb.

Důležitá rozhraní API

Úvod

Datová vazba je technika, která umožňuje, aby uživatelské rozhraní vaší aplikace efektivně zobrazovala a synchronizovala data. Oddělením obav z dat od obav uživatelského rozhraní zjednodušuje návrh aplikace, vylepšuje čitelnost a zlepšuje udržovatelnost.

Datovou vazbu můžete použít k jednoduchému zobrazení hodnot ze zdroje dat při prvním zobrazení uživatelského rozhraní, ale nereagování na změny v těchto hodnotách. Tento režim vazby se nazývá jednorázově a funguje dobře pro hodnotu, která se během běhu nemění. Alternativně můžete zvolit, že chcete hodnoty sledovat a aktualizovat uživatelské rozhraní při změně. Tento režim se nazývá jednosměrně a funguje dobře pro data jen pro čtení. Nakonec se můžete rozhodnout sledovat i aktualizovat, aby změny, které uživatel provede u hodnot v uživatelském rozhraní, byly automaticky vloženy zpět do zdroje dat. Tento režim se nazývá obousměrně a funguje dobře pro data pro čtení i zápis. Tady je několik příkladů.

  • Jednorázový režim můžete použít k vytvoření vazby obrázku na fotku aktuálního uživatele.
  • Jednosměrný režim můžete použít k vytvoření vazby ListView na kolekci článků zpráv v reálném čase seskupených podle oddílu novin.
  • Pomocí obousměrného režimu můžete vytvořit vazbu textového pole na jméno zákazníka ve formuláři.

Nezávisle na režimu existují dva druhy vazeb a obvykle deklarujete oba v kódu uživatelského rozhraní. Můžete použít buď rozšíření značek {x:Bind} , nebo rozšíření značek {Binding}. Můžete dokonce použít kombinaci těchto dvou ve stejné aplikaci – dokonce i na stejném prvku uživatelského rozhraní. {x:Bind} byl nový v UPW pro Windows 10 a má lepší výkon. Všechny podrobnosti popsané v tomto tématu platí pro oba druhy vazeb, pokud explicitně neřekneme jinak.

Ukázkové aplikace pro UWP, které demonstrují {x:Bind}

Ukázkové aplikace pro UWP, které předvádějí {Binding}

Každá vazba zahrnuje tyto části.

  • Zdroj vazby. Tento zdroj poskytuje data pro vazbu. Může to být instance jakékoli třídy, která má členy, jejichž hodnoty chcete zobrazit v uživatelském rozhraní.
  • Cíl vazby. Tento cíl je DependencyProperty u FrameworkElement ve vašem uživatelském rozhraní, který zobrazuje data.
  • Objekt vazby. Tento objekt přenáší datové hodnoty ze zdroje do cíle a volitelně z cíle zpět do zdroje. Objekt vazby se vytvoří v době načítání XAML z rozšíření značek {x:Bind} nebo {Binding} .

V následujících částech se podrobněji podíváte na zdroj vazby, cíl vazby a objekt vazby. Oddíly odkazují společně s příkladem vazby obsahu tlačítka na řetězcovou vlastnost s názvem NextButtonText, která patří do třídy s názvem HostViewModel.

Zdroj vazby

Tady je základní implementace třídy, kterou můžete použít jako zdroj vazby.

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

    public string NextButtonText { get; set; }
}

Tato implementace HostViewModela její vlastnost NextButtonTextfunguje pouze pro jednorázovou vazbu. Jednosměrné a obousměrné vazby jsou ale velmi běžné. V těchto typech vazeb se uživatelské rozhraní automaticky aktualizuje v reakci na změny datových hodnot zdroje vazby. Aby tyto druhy vazeb fungovaly správně, musíte zdroj vazby nastavit jako pozorovatelný pro objekt vazby. V našem příkladu tedy, pokud chcete jednosměrně nebo obousměrně navázat na vlastnost NextButtonText, pak jakékoliv změny, ke kterým dojde během běhu programu, musí být pozorovatelné objektem vazby.

Jedním ze způsobů, jak to udělat, je odvodit třídu, která představuje váš zdroj vazby z DependencyObject, a zveřejnit hodnotu dat prostřednictvím DependencyProperty*. To je způsob, jakým se FrameworkElement stává pozorovatelným. A FrameworkElement je dobrý zdroj vazby přímo z krabice.

Jednodušší způsob, jak vytvořit pozorovatelnou třídu a nezbytnou pro třídy, které již mají základní třídu, je implementovat System.ComponentModel.INotifyPropertyChanged. Tento přístup zahrnuje implementaci jedné události s názvem PropertyChanged. Příklad použití HostViewModel je znázorněn v následujícím kódu.

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

NextButtonText Nyní je vlastnost pozorovatelná. Když vytvoříte jednosměrnou nebo obousměrnou vazbu k této vlastnosti (ukážeme si, jak později), výsledný objekt vazby se přihlásí k odběru PropertyChanged události. Při vyvolání události obslužná rutina objektu vazby obdrží argument obsahující název vlastnosti, která se změnila. Takto objekt vazby ví, která hodnota vlastnosti se má znovu přečíst.

Takže pokud používáte C#, nemusíte implementovat vzor zobrazený dříve, můžete odvodit základní BindableBase třídu, kterou najdete v ukázce QuizGame (ve složce Common). Tady je příklad, jak to vypadá.

public class HostViewModel : BindableBase
{
    private string nextButtonText;

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

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

Vyvolání PropertyChanged události argumentem String.Empty nebo null indikuje, že všechny vlastnosti neindexeru objektu by měly být znovu přečteny. Událost můžete vyvolat, aby bylo možné indikovat, že se vlastnosti indexeru objektu změnily pomocí argumentu Item[indexer] pro konkrétní indexery (kde indexer je hodnota indexu) nebo hodnoty Item[] pro všechny indexery.

Zdroj vazby můžete považovat za jeden objekt, jehož vlastnosti obsahují data, nebo jako kolekci objektů. V kódu jazyka C# můžete jednorázově svázat s objektem, který implementuje seznam<T> , aby se zobrazila kolekce, která se nemění za běhu. Pro pozorovatelnou kolekci (když pozorujete přidávání a odebírání položek z kolekce) místo toho použijte jednosměrné vázání na ObservableCollection<T>. Pokud chcete vytvořit vazbu s vlastními třídami kolekce, postupujte podle pokynů v následující tabulce.

Scenario C# (CLR) C++/WinRT
Vytvoření vazby k objektu Může to být libovolný objekt. Může to být libovolný objekt.
Umožňuje získat oznámení o změnách vlastností z vázaného objektu. Objekt musí implementovat INotifyPropertyChanged. Objekt musí implementovat INotifyPropertyChanged.
Vytvoření vazby k kolekci Seznam<T> IVectorIInspectable nebo IBindableObservableVector. Podívejte se na ovládací prvky položek XAML; vytvořte vazbu na kolekci C++/WinRT a kolekce pomocí C++/WinRT.
Získejte oznámení o změnách kolekcí z vázané kolekce. ObservableCollection<T> IObservableVector z IInspectable. Například winrt::single_threaded_observable_vector<T>.
Implementujte kolekci, která podporuje vazbu. Extend List<T> nebo implementovat IList, IList<Object>, IEnumerable nebo IEnumerable<Object>. Vazba na obecné IList<T> a IEnumerable<T> není podporována. Implementujte IVector z IInspectable. Podívejte se na ovládací prvky položek XAML; vytvořte vazbu na kolekci C++/WinRT a kolekce pomocí C++/WinRT.
Implementujte kolekci, která podporuje oznámení o změnách kolekce. Extend ObservableCollection<T> nebo implementujte (negenerické) IList a INotifyCollectionChanged. Implementujte IObservableVector, IInspectable nebo IBindableObservableVector.
Implementujte kolekci, která podporuje přírůstkové načítání. Extend ObservableCollection<T> nebo implementujte (negenerické) IList a INotifyCollectionChanged. Kromě toho implementujte ISupportIncrementalLoading. Implementujte IObservableVector z IInspectable, nebo IBindableObservableVector. Kromě toho implementujte ISupportIncrementalLoading.

Ovládací prvky seznamu můžete svázat s libovolnými velkými zdroji dat a dosáhnout vysokého výkonu pomocí přírůstkového načítání. Můžete například vytvořit vazbu ovládacích prvků seznamu na výsledky dotazů obrázků Bingu, aniž byste museli načíst všechny výsledky najednou. Místo toho načtete jenom některé výsledky okamžitě a podle potřeby načtete další výsledky. Pokud chcete podporovat přírůstkové načítání, musíte implementovat ISupportIncrementalLoading ve zdroji dat, který podporuje oznámení o změnách kolekce. Když modul datových vazeb požaduje více dat, musí zdroj dat provést příslušné požadavky, integrovat výsledky a pak odeslat příslušná oznámení, aby bylo možné aktualizovat uživatelské rozhraní.

Cíl vazby

V následujících dvou příkladech je vlastnost Button.Content cílem vazby. Jeho hodnota je nastavena pomocí rozšíření značkování, které deklaruje objekt vazby. První příklad ukazuje {x:Bind} a druhý příklad ukazuje {Binding}. Deklarování vazeb v kódu je běžným případem, protože je pohodlné, čitelné a použitelné. Pokud ale potřebujete, můžete se vyhnout značkám a imperativně (programově) vytvořit instanci třídy Binding.

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

Pokud používáte C++/WinRT, musíte přidat atribut BindableAttribute do jakékoli třídy modulu runtime, se kterou chcete použít rozšíření značek {Binding} .

Důležité

Pokud používáte C++/WinRT, je atribut BindableAttribute dostupný v sadě Windows App SDK. Bez tohoto atributu musíte implementovat rozhraní ICustomPropertyProvider a ICustomProperty, aby bylo možné použít značku {Binding}.

Objekt vazby deklarovaný pomocí {x:Bind}

Před vytvořením kódu {x:Bind} musíte vystavit zdrojovou třídu vazby z třídy, která představuje vaši stránku revizí. Přidejte do své třídy okna vlastnost (v tomto případě typu HostViewModel).

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

Po přidání vlastnosti se můžete blíže podívat na značení, které deklaruje objekt pro vazbu. Následující příklad používá stejný Button.Content cíl vazby, který jste viděli v části Cíl vazby dříve. Zobrazuje cíl vazby, který je vázán na HostViewModel.NextButtonText vlastnost.

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

Všimněte si hodnoty, kterou zadáte pro Path. Okno interpretuje tuto hodnotu ve vlastním kontextu. V tomto případě cesta začíná odkazem na ViewModel vlastnost, kterou jste právě přidali na MainWindow stránku. Tato vlastnost vrátí instanci HostViewModel, takže můžete pomocí tečkové notace přistoupit k vlastnosti HostViewModel.NextButtonText na tomto objektu. Mode Určíte, že chcete přepsat výchozí hodnotu {x:Bind} jednorázového nastavení.

Vlastnost Path podporuje řadu možností syntaxe pro vazbu na vnořené vlastnosti, připojené vlastnosti a celočíselné a řetězcové indexery. Další informace najdete v tématu Syntaxe cesty vlastností. Vazba na řetězcové indexery vám umožňuje dosáhnout vazby na dynamické vlastnosti bez nutnosti implementovat ICustomPropertyProvider. Další nastavení najdete v tématu {x:Bind} rozšíření značek.

Chcete-li ilustrovat, že HostViewModel.NextButtonText vlastnost je pozorovatelná, přidejte obslužnou rutinu Click události na tlačítko a aktualizujte hodnotu HostViewModel.NextButtonText. Sestavte, spusťte a klikněte na tlačítko a zobrazte hodnotu aktualizace tlačítka Content .

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

Poznámka:

Změny TextBox.Text se posílají do obousměrného vázaného zdroje, když TextBox ztratí fokus, a ne po každém stisknutí klávesy uživatele.

DataTemplate a x:DataType

Uvnitř objektu DataTemplate (bez ohledu na to, jestli ji použijete jako šablonu položky, šablonu obsahu nebo šablonu záhlaví), nebude hodnota Path interpretována v kontextu okna. Místo toho funguje v kontextu datového objektu, který šablonujete. Při použití {x:Bind} v šabloně dat můžete ověřit jeho vazby v době kompilace a vygenerovat pro ně efektivní kód. Aby to bylo možné, DataTemplate musí deklarovat typ datového objektu pomocí x:DataType. Následující příklad by mohl být použit jako ItemTemplate ovládací prvek seznamu položek svázaný s kolekcí SampleDataGroup objektů.

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

Slabě zadané objekty v cestě

Předpokládejme, že máte typ, SampleDataGroup který implementuje řetězcovou vlastnost s názvem Title. Máte také vlastnost MainWindow.SampleDataGroupAsObject , která je typu object, ale ve skutečnosti vrací instanci SampleDataGroup. Výsledkem vazby <TextBlock Text="{x:Bind SampleDataGroupAsObject.Title}"/> je chyba kompilace, protože Title vlastnost nebyla nalezena v typu object. Pokud chcete tuto chybu opravit, přidejte přetypování do syntaxe Path takto: <TextBlock Text="{x:Bind ((data:SampleDataGroup)SampleDataGroupAsObject).Title}"/>. Tady je další příklad, kde Element je deklarován jako object , ale ve skutečnosti je : TextBlock<TextBlock Text="{x:Bind Element.Text}"/>. Přetypování tento problém řeší: <TextBlock Text="{x:Bind ((TextBlock)Element).Text}"/>.

Pokud se data načítají asynchronně

Částečné třídy pro windows generují kód pro podporu {x:Bind} v době kompilace. Tyto soubory najdete ve složce obj s názvy jako (pro C#). <view name>.g.cs Vygenerovaný kód obsahuje obslužnou rutinu události Načítání okna. Tato obslužná rutina volá metodu Initialize ve vygenerované třídě, která představuje vazby okna. Initialize volání Update pro zahájení přesouvání dat mezi zdrojem vazby a cílem. Loading je vyvolána těsně před předáním první míry okna nebo uživatelského ovládacího prvku. Pokud se data načítají asynchronně, nemusí být v době volání Initialize připravena. Po načtení dat můžete jednorázové vazby inicializovat voláním this.Bindings.Update();. Pokud potřebujete pouze jednorázové vazby pro asynchronně načtená data, je mnohem levnější je inicializovat tímto způsobem, než mít jednosměrné vazby a naslouchat změnám. Pokud vaše data neprocházejí jemně odstupňovanými změnami a pravděpodobně se aktualizují jako součást konkrétní akce, můžete vytvořit vazby jednorázově a kdykoli vynutit ruční aktualizaci voláním Update.

Poznámka:

{x:Bind} není vhodný pro scénáře s pozdní vazbou, jako je například navigace ve struktuře slovníku objektu JSON ani pro duck typing. "Duck typeing" je slabá forma psaní na základě lexikálních shod na názvech vlastností (stejně jako "pokud jde, plave a kurvy jako kachna, pak je to kachna"). Při psaní kachny by vazba na Age vlastnost byla stejně spokojena s objektem PersonWine nebo objektem (za předpokladu, že každý z těchto typů měl Age vlastnost). Pro tyto scénáře použijte {Binding} rozšíření značek.

Objekt vazby deklarovaný pomocí {Binding}

Pokud používáte C++/WinRT, přidejte atribut BindableAttribute do jakékoli třídy modulu runtime, ke které chcete vytvořit vazbu při použití rozšíření značek {Binding} . Pokud chcete použít {x:Bind}, tento atribut nepotřebujete.

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

Důležité

Pokud používáte C++/WinRT, je atribut BindableAttribute dostupný v sadě Windows App SDK. Bez tohoto atributu musíte implementovat rozhraní ICustomPropertyProvider a ICustomProperty, aby bylo možné použít rozšíření značky {Binding}.

Ve výchozím nastavení {Binding} předpokládá, že používáte vazbu na DataContext ve vašem značkovacím okně. Proto nastavte DataContext okno na instanci vaší třídy zdroje vazby (v tomto případě typ HostViewModel ). Následující příklad ukazuje kód, který deklaruje objekt vazby. Používá stejný Button.Content cíl vazby použitý dříve v části Cíl vazby a vytvoří vazbu na HostViewModel.NextButtonText vlastnost.

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

Všimněte si hodnoty zadané pro Path. DataContext okna interpretuje tuto hodnotu, která je v tomto příkladu nastavena na instanci HostViewModel. Cesta odkazuje na HostViewModel.NextButtonText vlastnost. Můžete vynechat Mode, protože výchozí nastavení jednosměrného {Binding} zde funguje správně.

Výchozí hodnota DataContext prvku uživatelského rozhraní je zděděná hodnota nadřazeného prvku. Toto výchozí nastavení DataContext můžete explicitně přepsat, přičemž je toto nastavení děděno podřízenými položkami automaticky. Nastavení DataContext explicitně u elementu je užitečné, pokud chcete mít více vazeb, které používají stejný zdroj.

Objekt vazby má Source vlastnost, která ve výchozím nastavení DataContext prvku uživatelského rozhraní, na kterém je vazba deklarována. Toto výchozí nastavení můžete přepsat nastavením Source, RelativeSourcenebo ElementName explicitně u vazby (podrobnosti najdete v tématu {Binding} ).

Uvnitř DataTemplate se DataContext automaticky nastaví na objekt dat, který je šablonován. Následující příklad lze použít jako ItemTemplate ovládací prvek položky vázané na kolekci libovolného typu, který má vlastnosti řetězce pojmenované Title a Description.

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

Poznámka:

Ve výchozím nastavení se změny TextBox.Text posílají do obousměrného vázaného zdroje, když TextBox ztratí fokus. Chcete-li způsobit odeslání změn po každém stisknutí klávesy uživatele, nastavte UpdateSourceTrigger na PropertyChanged vazbu v kódu. Můžete také zcela převzít kontrolu nad tím, kdy se změny odesílají do zdroje nastavením UpdateSourceTrigger na Explicit. Potom zpracujete události v textovém poli (obvykle TextBox.TextChanged), volání GetBindingExpression v cíli získat BindingExpression objektu a nakonec volat BindingExpression.UpdateSource programově aktualizovat zdroj dat.

Vlastnost Path podporuje řadu možností syntaxe pro vazbu na vnořené vlastnosti, připojené vlastnosti a celočíselné a řetězcové indexery. Další informace najdete v tématu Syntaxe cesty vlastností. Vazba na řetězcové indexery poskytuje účinek vazby na dynamické vlastnosti bez nutnosti implementovat ICustomPropertyProvider. Vlastnost ElementName je užitečná pro vazby element-to-element. Vlastnost RelativeSource má několik použití, z nichž jeden je jako výkonnější alternativa k vazbě šablony uvnitř ControlTemplate. Další nastavení najdete v tématu {Binding} rozšíření značek a třídy Binding .

Co když zdroj a cíl nejsou stejného typu?

Pokud chcete řídit viditelnost prvku uživatelského rozhraní na základě hodnoty logické vlastnosti nebo pokud chcete vykreslit prvek uživatelského rozhraní barvou, která je funkcí oblasti nebo trendu číselné hodnoty, nebo pokud chcete zobrazit hodnotu data a času ve vlastnosti prvku uživatelského rozhraní, která očekává řetězec, pak je potřeba převést hodnoty z jednoho typu na jiný. Existují případy, kdy správné řešení je odhalit další vlastnost správného typu ze zdrojové třídy vazby a ponechat logiku převodu zapouzdřenou a testovatelnou tam. Toto řešení ale není flexibilní ani škálovatelné, pokud máte velké množství nebo velké kombinace zdrojových a cílových vlastností. V takovém případě máte několik možností:

  • Pokud použijete {x:Bind} tuto akci, můžete svázat přímo s funkcí.
  • Nebo můžete zadat převaděč hodnot, který je objekt navržený k provedení převodu.

Převaděče hodnot

Tady je převaděč hodnot vhodný pro jednorázovou nebo jednosměrnou vazbu, která převede hodnotu DateTime na string hodnotu obsahující měsíc. Třída implementuje IValueConverter.

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

A tady je postup, jak tento převaděč hodnot v kódu objektu vazby.

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

Modul vazeb volá metody Convert a ConvertBack , pokud je pro vazbu definován parametr Converter . Když se data předají ze zdroje, modul vazeb volá Convert vrácená data do cíle. Když se data předají z cíle (pro obousměrnou vazbu), modul vazeb zavolá ConvertBack a předá vrácená data do zdroje.

Převaděč má také volitelné parametry: ConverterLanguage, který umožňuje zadat jazyk, který se má použít v převodu, a ConverterParameter, který umožňuje předat parametr pro logiku převodu. Příklad, který používá parametr převaděče, viz IValueConverter.

Poznámka:

Pokud při převodu dojde k chybě, nevyvolejte výjimku. Místo toho vraťte DependencyProperty.UnsetValue, který zastaví přenos dat.

Chcete-li zobrazit výchozí hodnotu, která se má použít při každém překladu zdroje vazby, nastavte FallbackValue vlastnost u objektu vazby v kódu. To je užitečné pro zpracování chyb převodu a formátování. Je také užitečné svázat se zdrojovými vlastnostmi, které nemusí existovat u všech objektů v vázané kolekci heterogenních typů.

Pokud vytvoříte vazbu textového ovládacího prvku na hodnotu, která není řetězcem, modul datových vazeb převede hodnotu na řetězec. Pokud je hodnota referenční typ, modul datových vazeb načte řetězcovou hodnotu voláním ICustomPropertyProvider.GetStringRepresentation nebo IStringable.ToString pokud je k dispozici, a jinak zavolá Object.ToString. Všimněte si však, že vazební modul bude ignorovat jakoukoli ToString implementaci, která skryje implementaci základní třídy. Implementace podtřídy by místo toho měly přepsat metodu základní třídy ToString . Podobně v nativních jazycích se zdá, že všechny spravované objekty implementují ICustomPropertyProvider a IStringable. Všechna volání a GetStringRepresentationIStringable.ToString jsou však směrována na Object.ToString nebo přepsání této metody, a nikdy na novou ToString implementaci, která skryje implementaci základní třídy.

Poznámka:

Sada Windows Community Toolkit poskytuje nástroj BoolToVisibilityConverter. Převaděč se mapuje true na hodnotu výčtu Visible a false na Collapsed to, abyste mohli vytvořit vazbu Visibility vlastnosti na logickou hodnotu bez vytvoření převaděče. Chcete-li použít převaděč, váš projekt musí přidat balíček NuGet CommunityToolkit.WinUI.Converters .

Vazba funkce v {x:Bind}

{x:Bind} umožňuje poslední krok v cestě vazby jako funkce. Pomocí této funkce můžete provádět převody nebo vytvářet vazby, které závisí na více než jedné vlastnosti. Další informace naleznete v tématu Funkce v x:Bind.

Vazba elementu k elementu

Vlastnost jednoho elementu XAML lze svázat s vlastností jiného elementu XAML. Tady je příklad, jak tato vazba vypadá v kódu.

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

Slovníky prostředků s {x:Bind}

Rozšíření značek {x:Bind} závisí na generování kódu, takže potřebuje soubor s kódem obsahující konstruktor, který volá InitializeComponent (inicializuje vygenerovaný kód). Pokud chcete slovník prostředků znovu použít, vytvořte instanci jeho typu (aby se InitializeComponent volal) místo odkazování na jeho název souboru. Tady je příklad toho, co dělat, pokud máte existující slovník prostředků a chcete ho použít {x:Bind} .

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

Kombinování {x:Bind} a {Binding} v opakovaně použitelném stylu

Předchozí příklad ukázal, jak se používá {x:Bind} v DataTemplates. Můžete také vytvořit opakovaně použitelné styly, které kombinují rozšíření značek {x:Bind} i {Binding}. Tato kombinace je užitečná, pokud chcete svázat některé vlastnosti na kompilačně známé hodnoty pomocí {x:Bind} a dalším vlastnostem na hodnoty runtime DataContextu pomocí {Binding}.

Následující příklad ukazuje, jak vytvořit opakovaně použitelný styl tlačítka, který používá oba přístupy vazby:

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

Použití v MainWindow.xaml s modelem ViewModel, který poskytuje hodnoty modulu runtime:

<!-- 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 (DataContext, který poskytuje hodnoty vazby modulu runtime):

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

V tomto příkladu:

  • {Binding} používá se pro vlastnosti, které závisí na objektu DataContext (ButtonBackgroundBrush, ButtonForegroundBrush, ButtonHoverBrush).
  • {x:Bind} používá se pro vlastnosti, které jsou známé v čase kompilace a patří do samotného ResourceDictionary (DefaultIndicatorBrush, DefaultPressedBrush)
  • Styl je opakovaně použitelný a můžete ho použít na libovolné tlačítko.
  • Motivy za běhu jsou možné prostřednictvím objektu DataContext a stále využívají výkon statických {x:Bind} prvků.

Vazby událostí a příkazy ICommand

{x:Bind} podporuje funkci označovanou jako vazba událostí. Pomocí této funkce můžete určit obslužnou rutinu události pomocí vazby. Tato funkce je další možností pro zpracování událostí vedle zpracování pomocí metody v souboru kódu na pozadí. Předpokládejme, že máte ve třídě MainWindow obslužnou rutinu události ListViewDoubleTapped.

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

Událost DoubleTapped objektu ListView můžete svázat s metodou v MainWindow takto.

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

K zpracování události pomocí této techniky nemůžete použít přetížené metody. Také, pokud metoda, která zpracovává událost má parametry, pak musí být všechny přiřaditelné z typů všech parametrů události, v uvedeném pořadí. V tomto případě ListViewDoubleTapped není přetížen a nemá žádné parametry (ale přesto by bylo platné, i kdyby přijal dva object parametry).

Metoda vazby událostí je podobná implementaci a využití příkazů. Příkaz je vlastnost, která vrací objekt, který implementuje ICommand rozhraní. S příkazy pracují {x:Bind} i {Binding} . Takže nemusíte implementovat vzor příkazů několikrát, můžete použít DelegateCommand pomocnou třídu, kterou najdete v ukázce KvízGame UWP (ve složce Common).

Vazba na kolekci složek nebo souborů

Pomocí rozhraní API v oboru názvů Windows.Storage můžete načíst data složek a souborů v zabalených aplikacích Windows App SDK. Různé GetFilesAsync, GetFoldersAsync a GetItemsAsync metody však nevrací hodnoty, které jsou vhodné k propojení s ovládacími prvky seznamu. Místo toho je nutné vytvořit vazbu na návratové hodnoty GetVirtualizedFilesVector, GetVirtualizedFoldersVector a GetVirtualizedItemsVector metody FileInformationFactory třídy. Následující příklad kódu z StorageDataSource a GetVirtualizedFilesVector UWP ukázka ukazuje typický vzor použití. Nezapomeňte deklarovat funkci picturesLibrary v manifestu balíčku aplikace a potvrdit, že jsou obrázky ve složce knihovny Obrázky.

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

Tento přístup obvykle používáte k vytvoření zobrazení informací o souborech a složkách jen pro čtení. Můžete vytvořit obousměrné vazby na vlastnosti souboru a složky, například umožnit uživatelům hodnotit skladbu v hudebním zobrazení. Všechny změny však nejsou zachovány, dokud nevoláte příslušnou SavePropertiesAsync metodu (například MusicProperties.SavePropertiesAsync). Změny byste měli potvrdit, když položka ztratí fokus, protože tato akce aktivuje resetování výběru.

Všimněte si, že obousměrná vazba pomocí této techniky funguje pouze s indexovanými umístěními, jako je například Hudba. Můžete určit, zda je umístění indexováno voláním FolderInformation.GetIndexedStateAsync metoda.

Všimněte si také, že virtualizovaný vektor může vrátit null některé položky předtím, než naplní jejich hodnotu. Měli byste například zkontrolovat null , než použijete hodnotu SelectedItem ovládacího prvku seznamu vázaného na virtualizovaný vektor, nebo místo toho použít SelectedIndex .

Vazba na data seskupené podle klíče

Pokud vezmete plochou kolekci položek (například knihy reprezentované BookSku třídou) a položky seskupíte pomocí společné vlastnosti jako klíče ( BookSku.AuthorName například vlastnosti), pak se výsledek nazývá seskupené data. Když data seskupíte, už se nejedná o plochou kolekci. Seskupené data jsou kolekce objektů skupiny, kde každý objekt skupiny obsahuje:

  • klíč a
  • kolekce položek, jejichž vlastnost odpovídá danému klíči.

Pokud chcete znovu vzít příklad knih, výsledkem seskupení knih podle jména autora je kolekce skupin jmen autorů, ve kterých každá skupina obsahuje:

  • klíč, což je jméno autora a
  • kolekce BookSku objektů, jejichž AuthorName vlastnost odpovídá klíči skupiny.

Obecně platí, že chcete-li zobrazit kolekci, vytvořte vazbu ItemsSource ovládacího prvku items (například ListView nebo GridView) přímo na vlastnost, která vrací kolekci. Pokud se jedná o plochou kolekci položek, nemusíte dělat nic zvláštního. Pokud se ale jedná o kolekci objektů skupiny (stejně jako při vazbě k seskupeným datům), potřebujete služby zprostředkujícího objektu označovaného jako CollectionViewSource , který se nachází mezi ovládacím prostředkem položek a zdrojem vazby. Vytvoříte vazbu na CollectionViewSource vlastnost, která vrací seskupené data, a vytvoříte vazbu položek ovládacího prvku CollectionViewSource. Další přidaná CollectionViewSource hodnota je, že udržuje přehled o aktuální položce, takže můžete udržovat více než jeden ovládací prvek položky v synchronizaci tím, že je všechny propojí se stejnými CollectionViewSource. K aktuální položce lze také přistupovat programově prostřednictvím ICollectionView.CurrentItem vlastnost objektu vrácené CollectionViewSource.View vlastnost.

Chcete-li aktivovat seskupovací zařízení CollectionViewSource, nastavte IsSourceGrouped na true. To, zda také potřebujete nastavit vlastnost ItemsPath , závisí přesně na tom, jak vytvoříte objekty skupiny. Existují dva způsoby, jak vytvořit objekt skupiny: vzor "is-a-group" a vzor "has-a-group". V modelu "is-a-group" je objekt skupiny odvozen z typu kolekce (například List<T>), takže objekt skupiny je ve skutečnosti sám skupina položek. S tímto vzorem nemusíte nastavovat ItemsPath. V vzoru "has-a-group" má objekt skupiny jednu nebo více vlastností typu kolekce (například List<T>), takže skupina "má" skupinu položek ve formě vlastnosti (nebo několik skupin položek ve formě několika vlastností). Pomocí tohoto vzoru je nutné nastavit ItemsPath název vlastnosti, která obsahuje skupinu položek.

Následující příklad znázorňuje vzor "má skupinu". Třída okna má vlastnost s názvem DataContext, která vrací instanci našeho modelu zobrazení. CollectionViewSource vytvoří vazbu na Authors vlastnost modelu zobrazení (Authors je kolekce objektů skupiny) a také určuje, že je Author.BookSkus to vlastnost, která obsahuje seskupené položky. GridView je vázán na CollectionViewSourcea má definovaný styl skupiny, aby mohl vykreslit položky ve skupinách.

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

Model is-a-group můžete implementovat jedním ze dvou způsobů. Jedním ze způsobů je vytvoření vlastní třídy skupiny. Odvození třídy z List<T> (kde T je typ položek). Například: public class Author : List<BookSku>. Druhým způsobem je použití výrazu LINQ k dynamickému vytváření objektů skupiny (a třídy skupiny) z hodnot vlastností položek BookSku . Tento přístup je typický pro aplikaci, která přistupuje k datům z cloudové služby. Získáte flexibilitu při seskupování knih podle autora nebo žánru (například) bez nutnosti speciálních skupinových tříd, jako je Autor a Žánr.

Následující příklad ukazuje vzor is-a-group pomocí LINQ. Tentokrát seskupíme knihy podle žánru, které se zobrazí s názvem žánru v záhlaví skupiny. Toto seskupení je označeno cestou vlastnosti "Klíč" v odkazu na hodnotu klíče skupiny.

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

Mějte na paměti, že při použití {x:Bind} s datovými šablonami je potřeba určit typ, ke kterému je vázáno, nastavením x:DataType hodnoty. Pokud je typ obecný, nemůžete ho vyjádřit ve značkách, takže místo toho musíte použít {Binding} v šabloně záhlaví stylu skupiny.

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

Ovládací prvek SémanticZoom je skvělý způsob, jak uživatelé zobrazit a procházet seskupovaná data. Ukázková aplikace Bookstore2 pro UPW ukazuje, jak používat SemanticZoom. V této aplikaci můžete zobrazit seznam knih seskupených podle autora (přiblížení v zobrazení) nebo můžete oddálit a zobrazit seznam autorů přeskakování (oddálit zobrazení). Seznam skoků nabízí mnohem rychlejší navigaci než procházení seznamu knih. Přiblížení a oddálení zobrazení jsou ve skutečnosti ListView nebo GridView ovládací prvky svázané se stejnými CollectionViewSource.

Obrázek SémanticZoom

Při vytváření vazby k hierarchickým datům , jako jsou podkategorie v kategoriích, můžete zvolit zobrazení hierarchických úrovní v uživatelském rozhraní pomocí řady ovládacích prvků položek. Výběr v jednom ovládacím prvku položek určuje obsah následných položek. Seznamy můžete udržovat synchronizované vazbou každého seznamu na vlastní CollectionViewSource a propojit CollectionViewSource instance dohromady v řetězu. Toto nastavení se nazývá zobrazení master/details (nebo list/details). Další informace najdete v tématu Vytvoření vazby k hierarchickým datům a vytvoření zobrazení předlohy a podrobností.

Diagnostika a ladění problémů s datovými vazbami

Kód vazby obsahuje názvy vlastností (a pro jazyk C# někdy pole a metody). Proto při přejmenování vlastnosti musíte také změnit všechny vazby, které na ni odkazují. Pokud to zapomenete udělat, vytvoříte chybu datové vazby a aplikace se buď nekompiluje nebo nespustí správně.

Objekty vazeb, které {x:Bind} a {Binding} vytvářejí, jsou z velké části funkčně ekvivalentní. Obsahuje ale {x:Bind} informace o typu pro zdroj vazby a generuje zdrojový kód v době kompilace. Díky {x:Bind}tomu získáte stejný druh detekce problémů, jaký získáte se zbytkem kódu. Tato detekce zahrnuje ověření doby kompilace vašich vazeb výrazů a ladění nastavením zarážek ve zdrojovém kódu vygenerovaném jako částečné třídy pro vaši stránku. Tyto třídy najdete v souborech ve složce obj s názvy jako (pro C#). <view name>.g.cs Pokud máte potíže s vazbou, zapněte přerušení při neošetřených výjimkách v ladicím programu Microsoft Visual Studio. Ladicí program v tomto okamžiku přeruší provádění a potom můžete ladit, co se nepovedlo. Kód vygenerovaný {x:Bind} pomocí stejného vzoru pro každou část grafu zdrojových uzlů vazeb a pomocí informací v okně Zásobník volání můžete určit posloupnost volání, která vedly k problému.

{Binding} nemá informace o typu pro zdroj vazby. Když ale spustíte aplikaci s připojeným ladicím programem, všechny chyby vazby se zobrazí v oknech Selhání vazeb XAML v sadě Visual Studio. Další informace o ladění chyb vazeb v sadě Visual Studio najdete v tématu Diagnostika datových vazeb XAML.

Vytváření vazeb v kódu

Poznámka:

Tento oddíl platí jenom pro {Binding}, protože v kódu nelze vytvářet vazby {x:Bind} . Můžete však dosáhnout některých stejných {x:Bind} výhod pomocí DependencyObject.RegisterPropertyChangedCallback, což umožňuje registrovat oznámení o změnách u jakékoli vlastnosti závislosti.

Prvky uživatelského rozhraní můžete k datům připojit také pomocí procedurálního kódu místo XAML. Chcete-li to provést, vytvořte nový Binding objekt, nastavte příslušné vlastnosti a pak volejte FrameworkElement.SetBinding nebo BindingOperations.SetBinding. Vytváření vazeb prostřednictvím kódu programu je užitečné, když chcete zvolit hodnoty vlastností vazby za běhu nebo sdílet jednu vazbu mezi více ovládacími prvky. Po volání SetBinding však nelze změnit hodnoty vlastnosti vazby.

Následující příklad ukazuje, jak implementovat vazbu v kódu.

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

Porovnání funkcí {x:Bind} a {Binding}

Vlastnost {x:Bind} vs. {Binding} Poznámky
Cesta je výchozí vlastnost. {x:Bind a.b.c}
-
{Binding a.b.c}
Path – vlastnost {x:Bind Path=a.b.c}
-
{Binding Path=a.b.c}
x:Bind Ve Pathvýchozím nastavení je v okně root, nikoli DataContext.
Indexer {x:Bind Groups[2].Title}
-
{Binding Groups[2].Title}
Vytvoří vazbu na zadanou položku v kolekci. Podporují se pouze celočíselné indexy.
Připojené vlastnosti {x:Bind Button22.(Grid.Row)}
-
{Binding Button22.(Grid.Row)}
Připojené vlastnosti jsou zadány pomocí závorek. Pokud vlastnost není deklarována v oboru názvů XAML, přiřaďte k ní předponu s oborem názvů XML, který by měl být namapován na obor názvů kódu v záhlaví dokumentu.
Odlévání {x:Bind groups[0].(data:SampleDataGroup.Title)}
-
Není potřeba pro {Binding}.
Přetypování se zadává pomocí závorek. Pokud vlastnost není deklarována v oboru názvů XAML, přiřaďte mu předponu s oborem názvů XML, který by měl být namapován na obor názvů kódu na začátku dokumentu.
Převodník {x:Bind IsShown, Converter={StaticResource BoolToVisibility}}
-
{Binding IsShown, Converter={StaticResource BoolToVisibility}}
Deklarujte převaděče v kořeni okna, ovládacího prvku, slovníku zdrojů nebo v App.xaml.
ConverterParameter, ConverterLanguage {x:Bind IsShown, Converter={StaticResource BoolToVisibility}, ConverterParameter=One, ConverterLanguage=fr-fr}
-
{Binding IsShown, Converter={StaticResource BoolToVisibility}, ConverterParameter=One, ConverterLanguage=fr-fr}
Deklarujte převaděče na úrovni kořene okna, ovládacího prvku, ResourceDictionary, nebo v souboru App.xaml.
TargetNullValue {x:Bind Name, TargetNullValue=0}
-
{Binding Name, TargetNullValue=0}
Používá se, když list vazbového výrazu má hodnotu null. Pro řetězcovou hodnotu použijte jednoduché uvozovky.
Náhradní hodnota {x:Bind Name, FallbackValue='empty'}
-
{Binding Name, FallbackValue='empty'}
Používá se, když jakákoli část cesty pro vazbu (s výjimkou listu) má hodnotu null.
ElementName {x:Bind slider1.Value}
-
{Binding Value, ElementName=slider1}
S {x:Bind} vazbou na pole Path je ve výchozím nastavení rootem okna, takže můžete přistupovat k libovolnému pojmenovaného prvku prostřednictvím jeho pole.
RelativeSource: Self <Rectangle x:Name="rect1" Width="200" Height="{x:Bind rect1.Width}" ... />
-
<Rectangle Width="200" Height="{Binding Width, RelativeSource={RelativeSource Self}}" ... />
S {x:Bind}, pojmenujte prvek a použijte jeho název v Path.
RelativeSource: TemplatedParent Není potřeba {x:Bind}
-
{Binding <path>, RelativeSource={RelativeSource TemplatedParent}}
{x:Bind} Při TargetTypeoznačení ControlTemplate vazby k nadřazené šabloně Pro {Binding}běžnou vazbu šablon lze použít v řídicích šablonách pro většinu použití. Ale použijte TemplatedParent tam, kde potřebujete použít převaděč nebo obousměrnou vazbu.
Zdroj Není potřeba {x:Bind}
-
<ListView ItemsSource="{Binding Orders, Source={StaticResource MyData}}"/>
Pro {x:Bind} můžete přímo použít pojmenovanou položku, použít vlastnost nebo statickou cestu.
Mode {x:Bind Name, Mode=OneWay}
-
{Binding Name, Mode=TwoWay}
Mode může být OneTime, OneWaynebo TwoWay. {x:Bind}výchozí hodnota ; OneTime{Binding} výchozí hodnota OneWayje .
UpdateSourceTrigger {x:Bind Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}
-
{Binding UpdateSourceTrigger=PropertyChanged}
UpdateSourceTrigger může být Default, LostFocusnebo PropertyChanged. {x:Bind} nepodporuje UpdateSourceTrigger=Explicit. {x:Bind} používá PropertyChanged chování pro všechny případy s výjimkou TextBox.Textpřípadů, kdy používá LostFocus chování.

Viz také