Přehled datových vazeb ve WPF

Datová vazba v Windows Presentation Foundation (WPF) poskytuje jednoduchý a konzistentní způsob, jak aplikace prezentovat data a pracovat s nimi. Prvky mohou být svázány s daty z různých zdrojů dat ve formě objektů .NET a XML. Všechny ContentControl takové položky, například a jakékoli ItemsControl, například ButtonListBox a ListView, mají předdefinované funkce, které umožňují flexibilní styly jednotlivých datových položek nebo kolekcí datových položek. Zobrazení řazení, filtrování a skupin se dají generovat nad daty.

Funkce datových vazeb ve WPF má oproti tradičním modelům několik výhod, včetně základní podpory datových vazeb širokou škálou vlastností, flexibilní reprezentací dat uživatelského rozhraní a čistým oddělením obchodní logiky od uživatelského rozhraní.

Tento článek nejprve popisuje koncepty základní pro datové vazby WPF a pak se zabývá používáním Binding třídy a dalších funkcí datové vazby.

Co je datová vazba?

Datová vazba je proces, který naváže spojení mezi uživatelským rozhraním aplikace a daty, která se zobrazí. Pokud má vazba správné nastavení a data poskytují správná oznámení, když data změní hodnotu, prvky vázané na data se automaticky změní. Datová vazba může také znamenat, že pokud se změní vnější reprezentace dat v elementu, podkladová data se dají automaticky aktualizovat tak, aby odrážela změnu. Pokud například uživatel upraví hodnotu v TextBox prvku, podkladová datová hodnota se automaticky aktualizuje tak, aby odrážela tuto změnu.

Typickým použitím datové vazby je umístit serverová nebo místní konfigurační data do formulářů nebo jiných ovládacích prvků uživatelského rozhraní. Ve WPF je tento koncept rozšířen tak, aby zahrnoval vazbu široké škály vlastností na různé zdroje dat. Ve WPF můžou být vlastnosti závislostí prvků vázány na objekty .NET (včetně ADO.NET objektů nebo objektů přidružených k webovým službám a webovým vlastnostem) a datům XML.

Příklad datové vazby najdete v následujícím uživatelském rozhraní aplikace z ukázky datové vazby, která zobrazuje seznam položek aukce.

Data binding sample screenshot

Aplikace ukazuje následující funkce datové vazby:

  • Obsah ListBox je vázán na kolekci AuctionItem objekty. Objekt AuctionItem má vlastnosti, jako je Description, StartPrice, StartDate, Category, SpecialFeatures atd.

  • Data (AuctionItem objects) zobrazená v ListBox šabloně, aby popis a aktuální cena byly zobrazeny pro každou položku. Šablona je vytvořena pomocí DataTemplate. Kromě toho vzhled jednotlivých položek závisí na hodnotě SpecialFeatureszobrazena AuctionItem . Pokud je hodnota SpecialFeatureshodnoty AuctionItemColor, položka má modré ohraničení. Pokud je hodnota Zvýrazněná, má položka oranžové ohraničení a hvězdičku. Část Šablonování dat poskytuje informace o šablonování dat.

  • Uživatel může data seskupit, filtrovat nebo řadit pomocí zadaného CheckBoxes pole. Na obrázku výše je vybraná možnost Seskupit podle kategoriía Seřadit podle kategorie a dataCheckBoxes . Možná jste si všimli, že se data seskupují podle kategorie produktu a název kategorie je v abecedním pořadí. Z obrázku je obtížné si všimnout, ale položky jsou také seřazené podle počátečního data v jednotlivých kategoriích. Řazení se provádí pomocí zobrazení kolekce. Oddíl Vazby k kolekcím popisuje zobrazení kolekcí.

  • Když uživatel vybere položku, ContentControl zobrazí se podrobnosti o vybrané položce. Toto prostředí se nazývá scénář s hlavními podrobnostmi. Část scénáře s hlavními podrobnostmi obsahuje informace o tomto typu vazby.

  • Typ vlastnosti StartDate je DateTime, který vrátí datum, které zahrnuje čas na milisekundu. V této aplikaci byl použit vlastní převaděč, aby se zobrazil kratší řetězec kalendářního data. Část Převod dat obsahuje informace o převaděčích.

Když uživatel vybere tlačítko Přidat produkt , zobrazí se následující formulář.

Add Product Listing page

Uživatel může upravit pole ve formuláři, zobrazit náhled výpisu produktů pomocí krátkých nebo podrobných podokn náhledů a vybrat Submit , jestli chcete přidat nový výpis produktů. Pro novou položku se použijí všechna existující nastavení seskupení, filtrování a řazení. V tomto konkrétním případě se položka zadaná na výše uvedeném obrázku zobrazí jako druhá položka v kategorii Počítač .

Na tomto obrázku se nezobrazuje ověřovací logika zadaná v počátečním datuTextBox. Pokud uživatel zadá neplatné datum (neplatné formátování nebo minulé datum), zobrazí se uživateli oznámení s ToolTip červeným vykřičníkem vedle TextBox. Část Ověření dat popisuje, jak vytvořit logiku ověřování.

Než začneme s různými funkcemi datových vazeb popsaných výše, nejprve probereme základní koncepty, které jsou důležité pro pochopení datové vazby WPF.

Základní koncepty datových vazeb

Bez ohledu na to, jaký prvek vytváříte vazbu a povahu zdroje dat, každá vazba vždy sleduje model ilustrovaný následujícím obrázkem.

Diagram that shows the basic data binding model.

Jak znázorňuje obrázek, datová vazba je v podstatě mostem mezi vaším cílem vazby a zdrojem vazby. Obrázek ukazuje následující základní koncepty datových vazeb WPF:

  • Každá vazba má obvykle čtyři komponenty:

    • Cílový objekt vazby.
    • Cílová vlastnost.
    • Zdroj vazby.
    • Cesta k hodnotě ve zdroji vazby, kterou chcete použít.

    Pokud například chcete svázat obsah TextBoxEmployee.Name vlastnosti, je TextBoxcílovým objektem vlastnost , cílová vlastnost je Text vlastnost, hodnota, která se má použít , a zdrojovým objektem je Employee objekt.

  • Cílová vlastnost musí být vlastnost závislosti. Většina UIElement vlastností je vlastností závislostí a většina vlastností závislostí kromě vlastností jen pro čtení ve výchozím nastavení podporuje datovou vazbu. (Pouze typy odvozené z DependencyObject mohou definovat vlastnosti závislostí; a všechny UIElement typy odvozené od DependencyObject.)

  • I když se na obrázku nezobrazuje, je třeba poznamenat, že zdrojový objekt vazby není omezen na vlastní objekt .NET. Datová vazba WPF podporuje data ve formě objektů .NET a XML. Pokud chcete uvést některé příklady, může být zdrojem vazby UIElementjakýkoli objekt seznamu, ADO.NET nebo objekt webových služeb nebo uzel XmlNode, který obsahuje data XML. Další informace najdete v tématu Přehled zdrojů vazeb.

Je důležité si uvědomit, že při vytváření vazby vytváříte vazbu cíl vazby ke zdroji vazeb. Pokud například zobrazujete některá podkladová data XML v datové vazbě ListBox pomocí datové vazby, jste ListBox svázání s daty XML.

K vytvoření vazby použijete Binding objekt. Zbytek tohoto článku popisuje mnoho konceptů spojených s objektem a některé vlastnosti a použití objektu Binding .

Směr toku dat

Jak je uvedeno šipkou na předchozím obrázku, tok dat vazby může přejít z cíle vazby na zdroj vazby (například se změní zdrojová hodnota, když uživatel upraví hodnotu TextBox) nebo ze zdroje vazby do cíle vazby (například váš TextBox obsah se aktualizuje o změny ve zdroji vazby), pokud zdroj vazby poskytuje správná oznámení.

Můžete chtít, aby vaše aplikace povolila uživatelům změnit data a rozšířit je zpět do zdrojového objektu. Nebo nechcete uživatelům povolit aktualizaci zdrojových dat. Tok dat můžete řídit nastavením Binding.Mode.

Tento obrázek znázorňuje různé typy toku dat:

Data binding data flow

  • OneWay vazba způsobí, že změny zdrojové vlastnosti automaticky aktualizují cílovou vlastnost, ale změny cílové vlastnosti se nešírují zpět do zdrojové vlastnosti. Tento typ vazby je vhodný, pokud je ovládací prvek vázán implicitně jen pro čtení. Můžete například vytvořit vazbu ke zdroji, jako je burzovní ticker, nebo třeba vaše cílová vlastnost nemá k dispozici žádné ovládací rozhraní pro provádění změn, například barvu pozadí vázaného na data tabulky. Pokud není nutné monitorovat změny cílové vlastnosti, použití OneWay režimu vazby zabrání režii TwoWay režimu vazby.

  • TwoWay vazba způsobí změny zdrojové vlastnosti nebo cílové vlastnosti, aby se ostatní automaticky aktualizovaly. Tento typ vazby je vhodný pro upravitelné formuláře nebo jiné plně interaktivní scénáře uživatelského rozhraní. Většina vlastností je výchozí pro OneWay vazbu, ale některé vlastnosti závislostí (obvykle vlastnosti uživatelsky upravitelných ovládacích prvků, jako je například TextBox.Texta CheckBox.IsChecked výchozí pro TwoWay vazbu). Programový způsob, jak určit, jestli vlastnost závislosti ve výchozím nastavení váže jednosměrně nebo obousměrně, je získat metadata vlastnosti a DependencyProperty.GetMetadata pak zkontrolovat logickou hodnotu FrameworkPropertyMetadata.BindsTwoWayByDefault vlastnosti.

  • OneWayToSource je obrácená vazba OneWay ; aktualizuje zdroj vlastnost při změně cílové vlastnosti. Jedním z ukázkových scénářů je, že potřebujete znovu vyhodnotit zdrojová hodnota z uživatelského rozhraní.

  • Není znázorněno na obrázku je OneTime vazba, která způsobí, že zdrojová vlastnost inicializuje cílovou vlastnost, ale nešířit následné změny. Pokud se kontext dat změní nebo objekt v kontextu dat změní, změna se neprojeví v cílové vlastnosti. Tento typ vazby je vhodný, pokud je vhodný snímek aktuálního stavu nebo jsou data skutečně statická. Tento typ vazby je také užitečný, pokud chcete inicializovat cílovou vlastnost s určitou hodnotou ze zdrojové vlastnosti a kontext dat není předem znám. Tento režim je v podstatě jednodušší formou vazby OneWay , která poskytuje lepší výkon v případech, kdy se zdrojová hodnota nezmění.

Chcete-li zjistit změny zdroje (použitelné pro OneWay a TwoWay vazby), musí zdroj implementovat vhodný mechanismus oznámení o změně vlastnosti, jako INotifyPropertyChangedje . Viz Postupy: Implementace oznámení o změně vlastnosti pro příklad INotifyPropertyChanged implementace.

Vlastnost Binding.Mode poskytuje další informace o režimech vazeb a příklad, jak určit směr vazby.

Co aktivuje aktualizace zdroje

Vazby, které jsou TwoWay nebo OneWayToSource naslouchají změnám v cílové vlastnosti, a šíří je zpět do zdroje, označované jako aktualizace zdroje. Můžete například upravit text textového pole a změnit tak podkladovou zdrojovou hodnotu.

Aktualizuje se ale zdrojová hodnota při úpravách textu nebo po dokončení úprav textu a ovládací prvek ztratí fokus? Vlastnost Binding.UpdateSourceTrigger určuje, co aktivuje aktualizaci zdroje. Tečky šipky vpravo na následujícím obrázku znázorňují roli Binding.UpdateSourceTrigger vlastnosti.

Diagram that shows the role of the UpdateSourceTrigger property.

UpdateSourceTrigger Pokud je UpdateSourceTrigger.PropertyChangedhodnota , pak hodnota, na kterou odkazuje šipka TwoWay vpravo nebo OneWayToSource vazby se aktualizuje, jakmile se cílová vlastnost změní. Pokud je LostFocusvšak UpdateSourceTrigger hodnota , tato hodnota se aktualizuje pouze novou hodnotou, když cílová vlastnost ztratí fokus.

Podobně jako u Mode vlastnosti mají různé vlastnosti závislostí různé výchozí UpdateSourceTrigger hodnoty. Výchozí hodnota pro většinu vlastností závislostí je PropertyChanged, zatímco TextBox.Text vlastnost má výchozí hodnotu LostFocus. PropertyChanged znamená, že ke zdrojovým aktualizacím obvykle dochází vždy, když se cílová vlastnost změní. Okamžité změny jsou v pořádku u zaškrtávacích políček a dalších jednoduchých ovládacích prvků. U textových polí ale může aktualizace po každém stisknutí klávesy snížit výkon a odepřít uživateli obvyklou příležitost k backspace a opravit chyby psaní před potvrzením nové hodnoty.

Informace o tom, jak najít výchozí hodnotu vlastnosti závislosti, najdete na UpdateSourceTrigger stránce vlastností.

Následující tabulka obsahuje ukázkový scénář pro každou UpdateSourceTrigger hodnotu pomocí příkladu TextBox .

Hodnota UpdateSourceTrigger Při aktualizaci zdrojové hodnoty Ukázkový scénář pro TextBox
LostFocus (výchozí hodnota pro TextBox.Text) Když ovládací prvek TextBox ztratí fokus. Textové pole, které je přidružené k ověřovací logice (viz ověření dat níže).
PropertyChanged Při psaní do .TextBox Ovládací prvky TextBox v okně chatovací místnosti
Explicit Když aplikace volá UpdateSource. Ovládací prvky TextBox v upravitelném formuláři (aktualizuje zdrojové hodnoty pouze v případech, kdy uživatel klikne na tlačítko odeslat).

Příklad najdete v tématu Postupy: Řízení, kdy text TextBox aktualizuje zdroj.

Vytvoření vazby

Chcete-li znovu vytvořit některé koncepty probírané v předchozích částech, vytvoříte vazbu pomocí objektu Binding a každá vazba má obvykle čtyři komponenty: cíl vazby, cílovou vlastnost, zdroj vazby a cestu ke zdrojové hodnotě, kterou chcete použít. Tato část popisuje, jak nastavit vazbu.

Představte si následující příklad, ve kterém je zdrojový objekt vazby třída s názvem MyData , která je definována v oboru názvů SDKSample . Pro demonstrační účely má MyData vlastnost řetězce s názvem ColorName , jejíž hodnota je nastavena na "Red". Tento příklad tedy vygeneruje tlačítko s červeným pozadím.

<DockPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
           xmlns:c="clr-namespace:SDKSample">
    <DockPanel.Resources>
        <c:MyData x:Key="myDataSource"/>
    </DockPanel.Resources>
    <DockPanel.DataContext>
        <Binding Source="{StaticResource myDataSource}"/>
    </DockPanel.DataContext>
    <Button Background="{Binding Path=ColorName}"
            Width="150" Height="30">
        I am bound to be RED!
    </Button>
</DockPanel>

Další informace o syntaxi deklarace vazby a příklady nastavení vazby v kódu najdete v tématu Přehled deklarací vazeb.

Pokud tento příklad použijeme u našeho základního diagramu, výsledný obrázek vypadá takto. Tento obrázek popisuje OneWay vazbu, protože vlastnost Background ve výchozím nastavení podporuje OneWay vazbu.

Diagram that shows the data binding Background property.

Možná vás zajímá, proč tato vazba funguje, i když vlastnost ColorName je typu řetězec, zatímco Background vlastnost je typu Brush. Tato vazba používá výchozí převod typu, který je popsán v části Převod dat .

Určení zdroje vazby

Všimněte si, že v předchozím příkladu je zdroj vazby určen nastavením DockPanel.DataContext vlastnost. Potom Button dědí DataContext hodnotu z objektu , který je jeho nadřazeným prvkem DockPanel. Chcete-li znovu zopakovat, zdrojový objekt vazby je jednou ze čtyř nezbytných součástí vazby. Bez zadaného zdrojového objektu vazby by tedy vazba nic neudělá.

Existuje několik způsobů, jak určit zdrojový objekt vazby. DataContext Použití vlastnosti nadřazeného elementu je užitečné, pokud vytváříte vazbu více vlastností na stejný zdroj. Někdy ale může být vhodnější určit zdroj vazby u jednotlivých deklarací vazeb. V předchozím příkladu můžete místo použití DataContext vlastnosti určit zdroj vazby nastavením Binding.Source vlastnosti přímo na deklaraci vazby tlačítka, jako v následujícím příkladu.

<DockPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
           xmlns:c="clr-namespace:SDKSample">
    <DockPanel.Resources>
        <c:MyData x:Key="myDataSource"/>
    </DockPanel.Resources>
    <Button Background="{Binding Source={StaticResource myDataSource}, Path=ColorName}"
            Width="150" Height="30">
        I am bound to be RED!
    </Button>
</DockPanel>

Kromě nastavení DataContext vlastnosti u elementu přímo, dědění DataContext hodnoty z nadřazeného objektu (například tlačítko v prvním příkladu) a explicitní zadání zdroje vazby nastavením Binding.Source vlastnosti na vazbu (například tlačítko v posledním příkladu), můžete také použít Binding.ElementName vlastnost nebo Binding.RelativeSource vlastnost k určení zdroje vazby. Tato ElementName vlastnost je užitečná, když vytváříte vazbu na jiné prvky v aplikaci, například když používáte posuvník k úpravě šířky tlačítka. Vlastnost RelativeSource je užitečná, pokud je vazba zadána v nebo ControlTemplateStyle. Další informace naleznete v tématu Postupy: Určení zdroje vazby.

Určení cesty k hodnotě

Pokud je zdrojem vazby objekt, použijte Binding.Path vlastnost k určení hodnoty, která se má použít pro vaši vazbu. Pokud vytváříte vazbu na data XML, použijte Binding.XPath vlastnost k určení hodnoty. V některých případech může být možné použít Path vlastnost i v případě, že data jsou XML. Pokud například chcete získat přístup k vlastnosti Name vráceného XmlNode (v důsledku dotazu XPath), měli byste použít Path vlastnost kromě XPath vlastnosti.

Další informace najdete v tématu Path a XPath vlastnosti.

I když jsme zdůraznili, že Path hodnota, kterou chcete použít, je jednou ze čtyř nezbytných součástí vazby, ve scénářích, které chcete svázat s celým objektem, by hodnota použitá byla stejná jako zdrojový objekt vazby. V těchto případech je možné nezadávat Path. Představte si následující příklad.

<ListBox ItemsSource="{Binding}"
         IsSynchronizedWithCurrentItem="true"/>

Výše uvedený příklad používá prázdnou syntaxi vazby: {Binding}. V tomto případě ListBox dědí DataContext z nadřazeného elementu DockPanel (není znázorněno v tomto příkladu). Pokud není zadána cesta, výchozí hodnota je vytvořit vazbu na celý objekt. Jinými slovy, v tomto příkladu byla cesta vynechána, protože vytváříme vazbu ItemsSource vlastnosti na celý objekt. (Podrobné informace najdete v části Vazba k kolekcím .)

Kromě vazby na kolekci je tento scénář užitečný také v případě, že chcete vytvořit vazbu na celý objekt místo pouze jedné vlastnosti objektu. Pokud je například zdrojový objekt typu String, můžete jednoduše chtít vytvořit vazbu k samotnému řetězci. Dalším běžným scénářem je vytvoření vazby elementu na objekt s několika vlastnostmi.

Možná budete muset použít vlastní logiku, aby data byla smysluplná pro vaši cílovou vlastnost. Vlastní logika může být ve formě vlastního převaděče, pokud neexistuje výchozí převod typu. Informace o převaděčích najdete v tématu Převod dat .

Vazby a BindingExpression

Než se pustíte do dalších funkcí a využití datových vazeb, je užitečné tuto třídu zavést BindingExpression . Jak jste viděli v předchozích částech, Binding třída je třída vysoké úrovně pro deklaraci vazby; poskytuje mnoho vlastností, které umožňují určit vlastnosti vazby. Související třída, BindingExpressionje základní objekt, který udržuje spojení mezi zdrojem a cílem. Vazba obsahuje všechny informace, které lze sdílet napříč několika vazbami výrazů. A BindingExpression je výraz instance, který nelze sdílet a obsahuje všechny informace o Bindinginstanci .

Vezměte v úvahu následující příklad, kde je instance MyData třídy, myBinding je zdrojový Binding objekt a MyData je definovaná třída, která obsahuje řetězcovou vlastnost s názvem ColorName.myDataObject Tento příklad vytvoří vazbu textového myTextobsahu instance , TextBlockna ColorName.

// Make a new source
var myDataObject = new MyData();
var myBinding = new Binding("ColorName")
{
    Source = myDataObject
};

// Bind the data source to the TextBox control's Text dependency property
myText.SetBinding(TextBlock.TextProperty, myBinding);
' Make a New source
Dim myDataObject As New MyData
Dim myBinding As New Binding("ColorName")
myBinding.Source = myDataObject

' Bind the data source to the TextBox control's Text dependency property
myText.SetBinding(TextBlock.TextProperty, myBinding)

K vytvoření dalších vazeb můžete použít stejný objekt myBinding . Objekt myBinding můžete například použít k vytvoření vazby textového obsahu zaškrtávacího políčka na ColorName. V tomto scénáři budou existovat dvě instance BindingExpression sdílení objektu myBinding .

Objekt BindingExpression se vrátí voláním GetBindingExpression objektu vázaného na data. Následující články ukazují některé z použití BindingExpression třídy:

Převod dat

V části Vytvoření vazby je tlačítko červené, protože jeho Background vlastnost je vázána na řetězcovou vlastnost s hodnotou "Red". Tato řetězcová hodnota funguje, protože převaděč typů je k dispozici na Brush typu pro převod řetězcové hodnoty na Brush.

Přidání těchto informací na obrázek v části Vytvoření vazby vypadá takto.

Diagram that shows the data binding Default property.

Co když ale místo vlastnosti typu string váš zdrojový objekt vazby má vlastnost Color typu Color? V takovém případě, aby vazba fungovala, je třeba nejprve změnit hodnotu vlastnosti Color na něco, co Background vlastnost přijímá. Budete muset vytvořit vlastní převaděč implementací IValueConverter rozhraní, jako v následujícím příkladu.

[ValueConversion(typeof(Color), typeof(SolidColorBrush))]
public class ColorBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        Color color = (Color)value;
        return new SolidColorBrush(color);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }
}
<ValueConversion(GetType(Color), GetType(SolidColorBrush))>
Public Class ColorBrushConverter
    Implements IValueConverter
    Public Function Convert(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.Convert
        Dim color As Color = CType(value, Color)
        Return New SolidColorBrush(color)
    End Function

    Public Function ConvertBack(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack
        Return Nothing
    End Function
End Class

Další informace naleznete v tématu IValueConverter.

Teď se vlastní převaděč používá místo výchozího převodu a náš diagram vypadá takto.

Diagram that shows the data binding custom converter.

Chcete-li znovu zopakovat, mohou být výchozí převody k dispozici z důvodu převaděčů typů, které jsou v daném typu vázány. Toto chování bude záviset na tom, které převaděče typů jsou v cíli k dispozici. Pokud máte pochybnosti, vytvořte vlastní převaděč.

Tady jsou některé typické scénáře, kdy dává smysl implementovat převaděč dat:

  • Vaše data by se měla zobrazovat odlišně v závislosti na jazykové verzi. Můžete například chtít implementovat převaděč měny nebo převaděč data a času kalendáře na základě konvencí používaných v konkrétní jazykové verzi.

  • Použitá data nemusí nutně změnit textovou hodnotu vlastnosti, ale je určená ke změně jiné hodnoty, například zdroje obrázku nebo barvy nebo stylu zobrazovaného textu. Převaděče lze v této instanci použít převodem vazby vlastnosti, která se nemusí zdát vhodná, například vazba textového pole na vlastnost Pozadí buňky tabulky.

  • Více než jeden ovládací prvek nebo více vlastností ovládacích prvků jsou svázány se stejnými daty. V tomto případě může primární vazba jenom zobrazit text, zatímco jiné vazby zpracovávají konkrétní problémy se zobrazením, ale stále používají stejnou vazbu jako informace o zdroji.

  • Cílová vlastnost má kolekci vazeb, které se označují MultiBindingjako . K MultiBindingvytvoření konečné hodnoty z hodnot vazeb použijete vlastní IMultiValueConverter hodnotu. Například barva může být vypočítáná z červených, modrých a zelených hodnot, což můžou být hodnoty ze stejných nebo různých zdrojových objektů vazby. Podívejte se MultiBinding na příklady a informace.

Vazba na kolekce

Zdrojový objekt vazby lze považovat za jeden objekt, jehož vlastnosti obsahují data, nebo jako kolekci dat polymorfních objektů, které se často seskupují dohromady (například výsledek dotazu do databáze). Zatím jsme probírali pouze vazbu na jednotlivé objekty. Vazba na kolekci dat je ale běžným scénářem. Běžným scénářem je například použití ItemsControl typu ListBox, nebo ListViewTreeView zobrazení kolekce dat, například v aplikaci uvedené v části Co je datová vazba.

Naštěstí náš základní diagram stále platí. Pokud vytváříte vazbu ItemsControl na kolekci, diagram vypadá takto.

Diagram that shows the data binding ItemsControl object.

Jak je znázorněno v tomto diagramu, vytvořit vazbu na ItemsControl objekt kolekce, ItemsControl.ItemsSource vlastnost je vlastnost, která se má použít. Můžete si představit ItemsSource jako obsah .ItemsControl Vazba je OneWay proto, ItemsSource že vlastnost ve výchozím nastavení podporuje OneWay vazbu.

Implementace kolekcí

Můžete vytvořit výčet všech kolekcí, které implementují IEnumerable rozhraní. Pokud ale chcete nastavit dynamické vazby tak, aby vložení nebo odstranění v kolekci aktualizovalo uživatelské rozhraní automaticky, musí kolekce implementovat INotifyCollectionChanged rozhraní. Toto rozhraní zveřejňuje událost, která by měla být vyvolána při každé změně podkladové kolekce.

WPF poskytuje ObservableCollection<T> třídu, což je integrovaná implementace kolekce dat, která zveřejňuje INotifyCollectionChanged rozhraní. Aby bylo možné plně podporovat přenos hodnot dat ze zdrojových objektů do cílů, musí každý objekt v kolekci, který podporuje svázatelné vlastnosti, také implementovat INotifyPropertyChanged rozhraní. Další informace najdete v tématu Přehled zdrojů vazeb.

Před implementací vlastní kolekce zvažte použití ObservableCollection<T> nebo některou ze stávajících tříd kolekcí, například List<T>, Collection<T>a BindingList<T>mimo jiné. Pokud máte pokročilý scénář a chcete implementovat vlastní kolekci, zvažte použití IList, která poskytuje ne generickou kolekci objektů, ke kterým může index přistupovat jednotlivě, a tím poskytuje nejlepší výkon.

Zobrazení kolekcí

Jakmile je svázaný ItemsControl s kolekcí dat, můžete je chtít seřadit, filtrovat nebo seskupit. K tomu použijete zobrazení kolekce, což jsou třídy, které implementují ICollectionView rozhraní.

Co jsou zobrazení kolekce?

Zobrazení kolekce je vrstva nad zdrojovou kolekcí vazeb, která umožňuje procházet a zobrazovat zdrojovou kolekci na základě řazení, filtrování a seskupení dotazů, aniž byste museli měnit samotnou podkladovou zdrojovou kolekci. Zobrazení kolekce také udržuje ukazatel na aktuální položku v kolekci. Pokud zdrojová kolekce implementuje INotifyCollectionChanged rozhraní, změny vyvolané událostí CollectionChanged se rozšíří do zobrazení.

Vzhledem k tomu, že zobrazení nemění podkladové zdrojové kolekce, může mít každá zdrojová kolekce přidružené více zobrazení. Můžete mít například kolekci objektů Task . Pomocí zobrazení můžete stejná data zobrazit různými způsoby. Na levé straně stránky můžete například chtít zobrazit úkoly seřazené podle priority a na pravé straně seskupené podle oblasti.

Vytvoření zobrazení

Jedním ze způsobů, jak vytvořit a použít zobrazení, je vytvořit instanci objektu zobrazení přímo a pak ho použít jako zdroj vazby. Představte si například ukázku aplikace datové vazby zobrazenou v části Co je datová vazba . Aplikace je implementovaná tak, aby ListBox vazby na zobrazení kolekce dat namísto přímo kolekce dat. Následující příklad se extrahuje z ukázkové aplikace datové vazby . Třída CollectionViewSource je proxy xaml třídy, která dědí z CollectionView. V tomto konkrétním příkladu Source je zobrazení vázané na kolekci AuctionItems (typu ObservableCollection<T>) aktuálního objektu aplikace.

<Window.Resources>
    <CollectionViewSource 
      Source="{Binding Source={x:Static Application.Current}, Path=AuctionItems}"   
      x:Key="listingDataView" />
</Window.Resources>

Prostředek výpisDataView pak slouží jako zdroj vazby pro prvky v aplikaci, jako je například ListBox.

<ListBox Name="Master" Grid.Row="2" Grid.ColumnSpan="3" Margin="8" 
         ItemsSource="{Binding Source={StaticResource listingDataView}}" />

Pokud chcete vytvořit další zobrazení pro stejnou kolekci, můžete vytvořit jinou CollectionViewSource instanci a dát jí jiný x:Key název.

Následující tabulka ukazuje, jaké datové typy zobrazení se vytvářejí jako výchozí zobrazení kolekce nebo na CollectionViewSource základě typu zdrojové kolekce.

Typ zdrojové kolekce Typ zobrazení kolekce Poznámky
IEnumerable Interní typ založený na CollectionView Položky nelze seskupit.
IList ListCollectionView Nejrychlejší.
IBindingList BindingListCollectionView

Použití výchozího zobrazení

Určení zobrazení kolekce jako zdroje vazeb je jedním ze způsobů, jak vytvořit a použít zobrazení kolekce. WPF také vytvoří výchozí zobrazení kolekce pro každou kolekci používanou jako zdroj vazby. Pokud vytvoříte vazbu přímo k kolekci, WPF vytvoří vazbu s výchozím zobrazením. Toto výchozí zobrazení sdílí všechny vazby do stejné kolekce, takže změna provedené ve výchozím zobrazení pomocí jednoho vázaného ovládacího prvku nebo kódu (například řazení nebo změny ukazatele aktuální položky, probírané později) se projeví ve všech ostatních vazbách do stejné kolekce.

Pokud chcete získat výchozí zobrazení, použijte metodu GetDefaultView . Příklad najdete v tématu Získání výchozího zobrazení kolekce dat.

Zobrazení kolekcí s ADO.NET datovými tabulkami

Pokud chcete zvýšit výkon, zobrazení kolekce pro ADO.NET DataTable nebo DataView objekty delegují řazení a filtrování na DataViewobjekty , což způsobí sdílení řazení a filtrování napříč všemi zobrazeními kolekce zdroje dat. Pokud chcete každému zobrazení kolekce povolit řazení a filtrování nezávisle, inicializujete každé zobrazení kolekce vlastním DataView objektem.

Řazení

Jak už bylo zmíněno dříve, zobrazení můžou u kolekce použít pořadí řazení. Jak existuje v podkladové kolekci, vaše data mohou nebo nemusí mít relevantní, základní pořadí. Zobrazení kolekce umožňuje uložit objednávku nebo změnit výchozí pořadí na základě zadaných kritérií porovnání. Vzhledem k tomu, že se jedná o zobrazení dat na základě klienta, je běžným scénářem, že uživatel může chtít seřadit sloupce tabulkových dat podle hodnoty, kterou sloupec odpovídá. Pomocí zobrazení lze toto uživatelem řízené řazení použít znovu, aniž byste museli provádět žádné změny v podkladové kolekci nebo dokonce muset znovu zobrazit dotaz na obsah kolekce. Příklad najdete v tématu Řazení sloupce GridView při kliknutí na záhlaví.

Následující příklad ukazuje logiku řazení "Seřadit podle kategorie a data" CheckBox uživatelského rozhraní aplikace v části Co je datové vazby .

private void AddSortCheckBox_Checked(object sender, RoutedEventArgs e)
{
    // Sort the items first by Category and then by StartDate
    listingDataView.SortDescriptions.Add(new SortDescription("Category", ListSortDirection.Ascending));
    listingDataView.SortDescriptions.Add(new SortDescription("StartDate", ListSortDirection.Ascending));
}
Private Sub AddSortCheckBox_Checked(sender As Object, e As RoutedEventArgs)
    ' Sort the items first by Category And then by StartDate
    listingDataView.SortDescriptions.Add(New SortDescription("Category", ListSortDirection.Ascending))
    listingDataView.SortDescriptions.Add(New SortDescription("StartDate", ListSortDirection.Ascending))
End Sub

Filtrování

Zobrazení můžou také použít filtr na kolekci, aby zobrazení zobrazovala jenom určitou podmnožinu celé kolekce. V datech můžete filtrovat podmínku. Například jak to dělá aplikace v části Co je datová vazba , obsahuje logiku CheckBox pro filtrování položek, které stojí 25 USD nebo více. Následující kód se spustí pro nastavení ShowOnlyBargainsFilter jako Filter obslužné rutiny události při CheckBox výběru.

private void AddFilteringCheckBox_Checked(object sender, RoutedEventArgs e)
{
    if (((CheckBox)sender).IsChecked == true)
        listingDataView.Filter += ListingDataView_Filter;
    else
        listingDataView.Filter -= ListingDataView_Filter;
}
Private Sub AddFilteringCheckBox_Checked(sender As Object, e As RoutedEventArgs)
    Dim checkBox = DirectCast(sender, CheckBox)

    If checkBox.IsChecked = True Then
        AddHandler listingDataView.Filter, AddressOf ListingDataView_Filter
    Else
        RemoveHandler listingDataView.Filter, AddressOf ListingDataView_Filter
    End If
End Sub

Obslužná rutina události ShowOnlyBargainsFilter má následující implementaci.

private void ListingDataView_Filter(object sender, FilterEventArgs e)
{
    // Start with everything excluded
    e.Accepted = false;

    // Only inlcude items with a price less than 25
    if (e.Item is AuctionItem product && product.CurrentPrice < 25)
        e.Accepted = true;
}
Private Sub ListingDataView_Filter(sender As Object, e As FilterEventArgs)

    ' Start with everything excluded
    e.Accepted = False

    Dim product As AuctionItem = TryCast(e.Item, AuctionItem)

    If product IsNot Nothing Then

        ' Only include products with prices lower than 25
        If product.CurrentPrice < 25 Then e.Accepted = True

    End If

End Sub

Pokud používáte některou z CollectionView tříd přímo místo CollectionViewSource, použijete Filter vlastnost k určení zpětného volání. Příklad najdete v tématu Filtrování dat v zobrazení.

Seskupování

Kromě interní třídy, která zobrazuje IEnumerable kolekci, podporují všechna zobrazení kolekcí seskupení, což uživateli umožňuje rozdělit kolekci v zobrazení kolekce do logických skupin. Skupiny můžou být explicitní, kde uživatel poskytne seznam skupin nebo implicitní, kde se skupiny generují dynamicky v závislosti na datech.

Následující příklad ukazuje logiku "Group by category" CheckBox.

// This groups the items in the view by the property "Category"
var groupDescription = new PropertyGroupDescription();
groupDescription.PropertyName = "Category";
listingDataView.GroupDescriptions.Add(groupDescription);
' This groups the items in the view by the property "Category"
Dim groupDescription = New PropertyGroupDescription()
groupDescription.PropertyName = "Category"
listingDataView.GroupDescriptions.Add(groupDescription)

Další příklad seskupení najdete v tématu Položky skupiny v objektu ListView, který implementuje GridView.

Ukazatele aktuální položky

Zobrazení také podporují pojem aktuální položky. Objekty můžete procházet v zobrazení kolekce. Při procházení přesouváte ukazatel položky, který umožňuje načíst objekt, který existuje v daném umístění v kolekci. Příklad: Projděte si objekty v objektu CollectionView.

Vzhledem k tomu, že WPF vytvoří vazbu na kolekci pouze pomocí zobrazení (buď zadaného zobrazení, nebo výchozího zobrazení kolekce), všechny vazby na kolekce mají ukazatel aktuální položky. Při vazbě k zobrazení určuje znak lomítka (/) v Path hodnotě aktuální položku zobrazení. V následujícím příkladu je kontext dat zobrazení kolekce. První řádek vytvoří vazbu k kolekci. Druhý řádek se sváže s aktuální položkou v kolekci. Třetí řádek vytvoří vazbu na Description vlastnost aktuální položky v kolekci.

<Button Content="{Binding }" />
<Button Content="{Binding Path=/}" />
<Button Content="{Binding Path=/Description}" />

Syntaxi lomítka a vlastnosti lze také naskládat tak, aby procházely hierarchii kolekcí. Následující příklad vytvoří vazbu na aktuální položku kolekce s názvem Offices, což je vlastnost aktuální položky zdrojové kolekce.

<Button Content="{Binding /Offices/}" />

Ukazatel aktuální položky může být ovlivněn řazením nebo filtrováním použitým v kolekci. Řazení zachová ukazatel aktuální položky na poslední vybranou položku, ale zobrazení kolekce je teď znovu strukturované. (Možná, že vybraná položka byla na začátku seznamu dříve, ale teď může být vybraná položka někde uprostřed.) Filtrování zachová vybranou položku, pokud tento výběr zůstane v zobrazení po filtrování. V opačném případě je ukazatel aktuální položky nastavený na první položku filtrovaného zobrazení kolekce.

Scénář vazby hlavních podrobností

Pojem aktuální položky je užitečný nejen pro navigaci položek v kolekci, ale také pro scénář vazby hlavních podrobností. Zvažte uživatelské rozhraní aplikace v části Co je datová vazba znovu. V této aplikaci výběr v rámci ListBox určuje obsah zobrazený v souboru ContentControl. Chcete-li ji vložit jiným způsobem, když je vybraná ListBox položka, ContentControl zobrazí se podrobnosti o vybrané položce.

Scénář s hlavními podrobnostmi můžete implementovat jednoduše tím, že máte dva nebo více ovládacích prvků svázaných se stejným zobrazením. Následující příklad z ukázky datové vazby ukazuje značky ListBox a ContentControl zobrazené v uživatelském rozhraní aplikace v části Co je datové vazby .

<ListBox Name="Master" Grid.Row="2" Grid.ColumnSpan="3" Margin="8" 
         ItemsSource="{Binding Source={StaticResource listingDataView}}" />
<ContentControl Name="Detail" Grid.Row="3" Grid.ColumnSpan="3"
                Content="{Binding Source={StaticResource listingDataView}}"
                ContentTemplate="{StaticResource detailsProductListingTemplate}" 
                Margin="9,0,0,0"/>

Všimněte si, že oba ovládací prvky jsou vázány na stejný zdroj, výpisDataView statický prostředek (viz definice tohoto prostředku v části Postup vytvoření zobrazení). Tato vazba funguje, protože když je jedenton objekt ( ContentControl v tomto případě) vázán na zobrazení kolekce, automaticky se sváže s CurrentItem zobrazením. Objekty CollectionViewSource automaticky synchronizují měnu a výběr. Pokud ovládací prvek seznamu není vázán na objekt, jako je v tomto příkladu CollectionViewSource , budete muset nastavit jeho IsSynchronizedWithCurrentItem vlastnost tak, aby true fungovala.

Další příklady najdete v tématu Vytvoření vazby k kolekci a zobrazení informací na základě výběru a použití vzoru podrobností předlohy s hierarchickými daty.

Možná jste si všimli, že výše uvedený příklad používá šablonu. Ve skutečnosti by se data nezobrazovat tak, jak chceme bez použití šablon (ten explicitně používá ContentControl a který implicitně používá ListBox). Teď se změníme na šablony dat v další části.

Šablony dat

Bez použití šablon dat by uživatelské rozhraní aplikace v části Co je datová vazba vypadalo takto.

Data Binding Demo without Data Templates

Jak je znázorněno v příkladu v předchozí části, ListBox ovládací prvek i ContentControl objekt jsou svázány s celým objektem kolekce (nebo konkrétněji zobrazením nad objektem kolekce) funkce AuctionItems. Bez konkrétních pokynů k zobrazení shromažďování ListBox dat se zobrazí řetězcová reprezentace každého objektu v podkladové kolekci a ContentControl zobrazí řetězcovou reprezentaci objektu, na který je vázán.

Aby aplikace tento problém vyřešila, definuje dataTemplates. Jak je znázorněno v příkladu v předchozí části, ContentControl explicitně používá šablonu dat detailsProductListingTemplate . Ovládací ListBox prvek implicitně používá následující šablonu dat při zobrazení objektů AuctionItem v kolekci.

<DataTemplate DataType="{x:Type src:AuctionItem}">
    <Border BorderThickness="1" BorderBrush="Gray"
            Padding="7" Name="border" Margin="3" Width="500">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="86"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>

            <Polygon Grid.Row="0" Grid.Column="0" Grid.RowSpan="4"
                     Fill="Yellow" Stroke="Black" StrokeThickness="1"
                     StrokeLineJoin="Round" Width="20" Height="20"
                     Stretch="Fill"
                     Points="9,2 11,7 17,7 12,10 14,15 9,12 4,15 6,10 1,7 7,7"
                     Visibility="Hidden" Name="star"/>

            <TextBlock Grid.Row="0" Grid.Column="1" Margin="0,0,8,0"
                       Name="descriptionTitle"
                       Style="{StaticResource smallTitleStyle}">Description:</TextBlock>
            
            <TextBlock Name="DescriptionDTDataType" Grid.Row="0" Grid.Column="2"
                       Text="{Binding Path=Description}"
                       Style="{StaticResource textStyleTextBlock}"/>

            <TextBlock Grid.Row="1" Grid.Column="1" Margin="0,0,8,0"
                       Name="currentPriceTitle"
                       Style="{StaticResource smallTitleStyle}">Current Price:</TextBlock>
            
            <StackPanel Grid.Row="1" Grid.Column="2" Orientation="Horizontal">
                <TextBlock Text="$" Style="{StaticResource textStyleTextBlock}"/>
                <TextBlock Name="CurrentPriceDTDataType"
                           Text="{Binding Path=CurrentPrice}" 
                           Style="{StaticResource textStyleTextBlock}"/>
            </StackPanel>
        </Grid>
    </Border>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding Path=SpecialFeatures}">
            <DataTrigger.Value>
                <src:SpecialFeatures>Color</src:SpecialFeatures>
            </DataTrigger.Value>
            <DataTrigger.Setters>
                <Setter Property="BorderBrush" Value="DodgerBlue" TargetName="border" />
                <Setter Property="Foreground" Value="Navy" TargetName="descriptionTitle" />
                <Setter Property="Foreground" Value="Navy" TargetName="currentPriceTitle" />
                <Setter Property="BorderThickness" Value="3" TargetName="border" />
                <Setter Property="Padding" Value="5" TargetName="border" />
            </DataTrigger.Setters>
        </DataTrigger>
        <DataTrigger Binding="{Binding Path=SpecialFeatures}">
            <DataTrigger.Value>
                <src:SpecialFeatures>Highlight</src:SpecialFeatures>
            </DataTrigger.Value>
            <Setter Property="BorderBrush" Value="Orange" TargetName="border" />
            <Setter Property="Foreground" Value="Navy" TargetName="descriptionTitle" />
            <Setter Property="Foreground" Value="Navy" TargetName="currentPriceTitle" />
            <Setter Property="Visibility" Value="Visible" TargetName="star" />
            <Setter Property="BorderThickness" Value="3" TargetName="border" />
            <Setter Property="Padding" Value="5" TargetName="border" />
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

S použitím těchto dvou datových templates je výsledné uživatelské rozhraní zobrazené v části Co je datové vazby . Jak vidíte na tomto snímku obrazovky, kromě toho, že vám umožní umístit data do ovládacích prvků, vám DataTemplates umožňují definovat působivé vizuály pro vaše data. Například DataTriggerve výše uvedeném DataTemplate příkladu se používají hodnoty AuctionItems s hodnotou SpecialFeaturesHighLight s oranžovým ohraničením a hvězdou.

Další informace o šablonách dat najdete v přehledu šablon dat.

Ověřování dat

Většina aplikací, které přebírají vstup uživatele, musí mít logiku ověření, aby se zajistilo, že uživatel zadal očekávané informace. Kontroly ověření můžou být založené na typu, rozsahu, formátu nebo jiných požadavcích specifických pro aplikaci. Tato část popisuje, jak funguje ověřování dat ve WPF.

Přidružení ověřovacích pravidel k vazbě

Model datové vazby WPF umožňuje přidružit ValidationRules k objektu Binding . Například následující příklad vytvoří vazbu TextBox na vlastnost pojmenovanou StartPrice a přidá ExceptionValidationRule objekt do Binding.ValidationRules vlastnosti.

<TextBox Name="StartPriceEntryForm" Grid.Row="2"
         Style="{StaticResource textStyleTextBox}" Margin="8,5,0,5" Grid.ColumnSpan="2">
    <TextBox.Text>
        <Binding Path="StartPrice" UpdateSourceTrigger="PropertyChanged">
            <Binding.ValidationRules>
                <ExceptionValidationRule />
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

Objekt ValidationRule zkontroluje, zda je hodnota vlastnosti platná. WPF má dva typy předdefinovaných ValidationRule objektů:

Můžete také vytvořit vlastní ověřovací pravidlo odvozením z ValidationRule třídy a implementací Validate metody. Následující příklad ukazuje pravidlo, které používá přidání výpisu produktů "Počáteční datum" TextBox z oddílu Co je datová vazba .

public class FutureDateRule : ValidationRule
{
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        // Test if date is valid
        if (DateTime.TryParse(value.ToString(), out DateTime date))
        {
            // Date is not in the future, fail
            if (DateTime.Now > date)
                return new ValidationResult(false, "Please enter a date in the future.");
        }
        else
        {
            // Date is not a valid date, fail
            return new ValidationResult(false, "Value is not a valid date.");
        }

        // Date is valid and in the future, pass
        return ValidationResult.ValidResult;
    }
}
Public Class FutureDateRule
    Inherits ValidationRule

    Public Overrides Function Validate(value As Object, cultureInfo As CultureInfo) As ValidationResult

        Dim inputDate As Date

        ' Test if date is valid
        If Date.TryParse(value.ToString, inputDate) Then

            ' Date is not in the future, fail
            If Date.Now > inputDate Then
                Return New ValidationResult(False, "Please enter a date in the future.")
            End If

        Else
            ' // Date Is Not a valid date, fail
            Return New ValidationResult(False, "Value is not a valid date.")
        End If

        ' Date is valid and in the future, pass
        Return ValidationResult.ValidResult

    End Function

End Class

Funkce StartDateEntryFormTextBox používá tuto funkci FutureDateRule, jak je znázorněno v následujícím příkladu.

<TextBox Name="StartDateEntryForm" Grid.Row="3"
         Validation.ErrorTemplate="{StaticResource validationTemplate}" 
         Style="{StaticResource textStyleTextBox}" Margin="8,5,0,5" Grid.ColumnSpan="2">
    <TextBox.Text>
        <Binding Path="StartDate" UpdateSourceTrigger="PropertyChanged" 
                 Converter="{StaticResource dateConverter}" >
            <Binding.ValidationRules>
                <src:FutureDateRule />
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

Vzhledem k tomu, že UpdateSourceTrigger hodnota je PropertyChanged, modul vazeb aktualizuje zdrojová hodnota při každém stisknutí kláves, což znamená, že také kontroluje každé pravidlo v kolekci ValidationRules na každém stisknutí kláves. Tento postup si probereme dále v části Proces ověřování.

Poskytnutí vizuální zpětné vazby

Pokud uživatel zadá neplatnou hodnotu, můžete chtít poskytnout zpětnou vazbu k chybě v uživatelském rozhraní aplikace. Jedním ze způsobů, jak poskytnout takovou zpětnou vazbu, je nastavit Validation.ErrorTemplate připojenou vlastnost na vlastní ControlTemplate. Jak je znázorněno v předchozím dílčím oddílu, StartDateEntryFormTextBox používá ErrorTemplate název validationTemplate. Následující příklad ukazuje definici validationTemplate.

<ControlTemplate x:Key="validationTemplate">
    <DockPanel>
        <TextBlock Foreground="Red" FontSize="20">!</TextBlock>
        <AdornedElementPlaceholder/>
    </DockPanel>
</ControlTemplate>

Prvek AdornedElementPlaceholder určuje, kam má být ovládací prvek odorován.

Kromě toho můžete také použít ToolTip k zobrazení chybové zprávy. StartDateEntryFormes i StartPriceEntryFormesTextBox používají styl textStyleTextBox, který vytvoří ToolTip chybovou zprávu. Následující příklad ukazuje definici textStyleTextBox. Připojená vlastnost Validation.HasError je true , když jedna nebo více vazeb u vlastností vázaného prvku je chybná.

<Style x:Key="textStyleTextBox" TargetType="TextBox">
    <Setter Property="Foreground" Value="#333333" />
    <Setter Property="MaxLength" Value="40" />
    <Setter Property="Width" Value="392" />
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="true">
            <Setter Property="ToolTip" 
                    Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
        </Trigger>
    </Style.Triggers>
</Style>

ErrorTemplate Pokud dojde k chybě ověření, vypadá vlastní a ToolTipstartDateEntryFormTextBox jako následující.

Data binding validation error

Pokud máte Binding přidružená ověřovací pravidla, ale nezadáte na ErrorTemplate vázaném ovládacím prvku, použije se výchozí nastavení ErrorTemplate k upozornění uživatelů, pokud dojde k chybě ověření. Výchozí ErrorTemplate je šablona ovládacího prvku, která definuje červené ohraničení ve vrstvě adorneru. Ve výchozím nastavení ErrorTemplate a ToolTipuživatelské rozhraní StartPriceEntryFormTextBox vypadá jako následující, pokud dojde k chybě ověření.

Data binding validation error default

Příklad, jak poskytnout logiku pro ověření všech ovládacích prvků v dialogovém okně, najdete v části Vlastní dialogová okna v přehledu dialogových oken.

Proces ověření

K ověření obvykle dochází, když je hodnota cíle přenesena do vlastnosti zdroje vazby. K tomuto přenosu dochází u TwoWay a OneWayToSource vazbách. Pokud chcete zopakovat, co způsobuje aktualizaci zdroje, závisí na hodnotě UpdateSourceTrigger vlastnosti, jak je popsáno v části Co triggers source updates oddíl.

Následující položky popisují proces ověření . Pokud během tohoto procesu dojde k chybě ověření nebo jinému typu chyby, proces se zastaví:

  1. Modul vazeb zkontroluje, jestli jsou definovány nějaké vlastní ValidationRule objekty, jejichž ValidationStep hodnota je RawProposedValue nastavena pro tento Binding, v takovém případě volá metodu Validate pro každou ValidationRule z nich, dokud jeden z nich nenarazí na chybu nebo dokud všechny neprojdou.

  2. Vazební modul pak zavolá převaděče, pokud existuje.

  3. Pokud převaděč proběhne úspěšně, modul vazeb zkontroluje, jestli existují nějaké vlastní ValidationRule objekty definované ValidationStep pro ConvertedProposedValue tento Bindingobjekt , v takovém případě volá metodu Validate pro každou ValidationRule z nich, která je ValidationStep nastavena na ConvertedProposedValue , dokud některý z nich nenarazí na chybu nebo dokud všechny neprojdou.

  4. Vazební modul nastaví zdroj vlastnost.

  5. Modul vazeb zkontroluje, jestli jsou definovány nějaké vlastní ValidationRule objekty, jejichž ValidationStep hodnota je UpdatedValue nastavena pro tento Binding, v takovém případě volá metodu Validate pro každý ValidationRule z nich, který je ValidationStep nastaven na UpdatedValue , dokud jeden z nich nenarazí na chybu nebo dokud všechny neprojdou. DataErrorValidationRule Pokud je vazba přidružená a její ValidationStep je nastavena na výchozí, UpdatedValueje zaškrtnuté v tomto okamžikuDataErrorValidationRule. V tomto okamžiku je zaškrtnuté všechny vazby, které mají nastavenou ValidatesOnDataErrors sadu true .

  6. Modul vazeb zkontroluje, jestli jsou definovány nějaké vlastní ValidationRule objekty, jejichž ValidationStep hodnota je CommittedValue nastavena pro tento Binding, v takovém případě volá metodu Validate pro každý ValidationRule z nich, který je ValidationStep nastaven na CommittedValue , dokud jeden z nich nenarazí na chybu nebo dokud všechny neprojdou.

ValidationRule Pokud se v průběhu tohoto procesu nepředá, vytvoří modul ValidationError vazby objekt a přidá ho do Validation.Errors kolekce vázaného prvku. Před spuštěním ValidationRule vazbového modulu objekty v libovolném kroku odebere všechny ValidationError přidané do Validation.Errors připojené vlastnosti vázaného prvku během tohoto kroku. Pokud ValidationRuleValidationStep například UpdatedValue dojde k selhání procesu ověření, modul vazeb ho odebere ValidationError bezprostředně před voláním libovolného ValidationStepValidationRule nastaveného UpdatedValuepříkazu .

Pokud Validation.Errors není prázdná, je připojená Validation.HasError vlastnost prvku nastavena na true. NotifyOnValidationError Pokud je vlastnost objektu Binding nastavena truena , pak modul vazby vyvolá připojenou Validation.Error událost na elementu.

Všimněte si také, že platný přenos hodnot v obou směrech (cíl na zdroj nebo zdroj do cíle) vymaže připojenou Validation.Errors vlastnost.

Pokud má vazba přidruženou ExceptionValidationRule k němu nebo je ValidatesOnExceptions vlastnost nastavena true a při nastavování zdroje modul vazeb vyvolá výjimku, zkontroluje modul vazby, zda existuje UpdateSourceExceptionFilter. Máte možnost použít UpdateSourceExceptionFilter zpětné volání k poskytnutí vlastní obslužné rutiny pro zpracování výjimek. Pokud není zadánBinding, UpdateSourceExceptionFilter vytvoří modul vazby ValidationError s výjimkou výjimku a přidá ho do Validation.Errors kolekce vázaného prvku.

Mechanismus ladění

Připojenou vlastnost PresentationTraceSources.TraceLevel u objektu souvisejícího s vazbou můžete nastavit tak, aby přijímala informace o stavu konkrétní vazby.

Viz také