Not
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Den här artikeln beskriver WinUI-databindningsfunktionerna med api:erna i namnområdet Microsoft.UI.Xaml.Data.
Anmärkning
I det här avsnittet beskrivs databindningsfunktioner i detalj. En kort, praktisk introduktion finns i Översikt över databindning.
Viktiga API:er
Introduction
Databindning är en teknik som gör att appens användargränssnitt kan visa och synkronisera data effektivt. Genom att separera dataproblem från användargränssnittsproblem förenklar det appdesignen, förbättrar läsbarheten och förbättrar underhållsmöjligheterna.
Du kan använda databindning för att helt enkelt visa värden från en datakälla när användargränssnittet först visas, men inte svara på ändringar i dessa värden. Det här bindningsläget kallas en gång och fungerar bra för ett värde som inte ändras under körningen. Du kan också välja att "observera" värdena och uppdatera användargränssnittet när de ändras. Det här läget kallas enkelriktat och fungerar bra för skrivskyddade data. I slutändan kan du välja att både observera och uppdatera, så att ändringar som användaren gör i värden i användargränssnittet automatiskt skickas tillbaka till datakällan. Det här läget kallas dubbelriktat och fungerar bra för skrivskyddade data. Här följer några exempel.
- Du kan använda engångsläget för att binda en bild till den aktuella användarens foto.
- Du kan använda enkelriktat läge för att binda en ListView till en samling nyhetsartiklar i realtid grupperade efter tidningsavsnitt.
- Du kan använda tvåvägsläget för att binda en textruta till en kunds namn i ett formulär.
Oberoende av läge finns det två typer av bindningar och du deklarerar vanligtvis båda i UI-markering. Du kan välja att använda markeringstillägget {x:Bind} eller {Binding}-markeringstillägget. Du kan till och med använda en blandning av de två i samma app , även i samma gränssnittselement.
{x:Bind} var nytt i UWP för Windows 10 och det har bättre prestanda. All information som beskrivs i det här avsnittet gäller för båda typerna av bindningar om vi inte uttryckligen säger något annat.
UWP-exempelappar som demonstrerar {x:Bind}
UWP-exempelappar som demonstrerar {Binding}
- Ladda ned UWP Bookstore1-appen .
- Ladda ned Bookstore2-appen .
Varje bindning omfattar dessa delar
- En bindningskälla. Den här källan tillhandahåller data för bindningen. Det kan vara en instans av alla klasser som har medlemmar vars värden du vill visa i användargränssnittet.
- Ett bindningsmål. Det här målet är en DependencyProperty för FrameworkElement i ditt användargränssnitt som visar data.
- Ett bindningsobjekt. Det här objektet överför datavärden från källan till målet och eventuellt från målet tillbaka till källan. Bindningsobjektet skapas vid XAML-inläsningstid från ditt {x:Bind} eller {Binding} -tillägg.
I följande avsnitt tar du en närmare titt på bindningskällan, bindningsmålet och bindningsobjektet. Avsnitten länkar tillsammans med exemplet med att binda en knapps innehåll till en strängegenskap med namnet NextButtonText, som tillhör en klass med namnet HostViewModel.
Bindningskälla
Här är en grundläggande implementering av en klass som du kan använda som bindningskälla.
public class HostViewModel
{
public HostViewModel()
{
NextButtonText = "Next";
}
public string NextButtonText { get; set; }
}
Implementeringen av HostViewModel, och dess egenskap NextButtonText, fungerar endast för engångsbindning. Men enkelriktade och dubbelriktade bindningar är extremt vanliga. I den här typen av bindning uppdateras användargränssnittet automatiskt som svar på ändringar i datavärdena för bindningskällan. För att den typen av bindning ska fungera korrekt måste du göra bindningskällan observerbar för bindningsobjektet. Så i vårt exempel, om du vill använda envägs- eller tvåvägsbindning till egenskapen NextButtonText, måste alla ändringar som sker under körning av värdet för den egenskapen kunna observeras av bindningsobjektet.
Ett sätt att göra det är att härleda klassen som representerar din bindningskälla från DependencyObject och exponera ett datavärde via en DependencyProperty*. Det är så ett FrameworkElement blir observerbart. A FrameworkElement är en bra bindningskälla direkt.
Ett enklare sätt att göra en klass observerbar – och ett nödvändigt för klasser som redan har en basklass – är att implementera System.ComponentModel.INotifyPropertyChanged. Den här metoden omfattar implementering av en enskild händelse med namnet PropertyChanged. Ett exempel som använder HostViewModel visas i följande kod.
...
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));
}
}
Nu är egenskapen NextButtonText observerbar. När du skapar en enkelriktad eller dubbelriktad bindning till den egenskapen (vi visar hur senare) prenumererar det resulterande bindningsobjektet på PropertyChanged händelsen. När händelsen utlöses tar bindningsobjektets hanterare emot ett argument som innehåller namnet på den egenskap som ändrades. Det är så bindningsobjektet vet vilken egenskaps värde som ska läsas igen.
Så att du inte behöver implementera mönstret som visades tidigare flera gånger, om du använder C#, kan du härleda från basklassen BindableBase som du hittar i QuizGame-exemplet (i mappen "Common"). Här är ett exempel på hur det ser ut.
public class HostViewModel : BindableBase
{
private string nextButtonText;
public HostViewModel()
{
NextButtonText = "Next";
}
public string NextButtonText
{
get { return nextButtonText; }
set { SetProperty(ref nextButtonText, value); }
}
}
PropertyChanged Att höja händelsen med argumentet String.Empty eller null anger att alla egenskaper som inte är indexerare för objektet ska läsas på nytt. Du kan höja händelsen för att indikera att indexerarens egenskaper för objektet har ändrats med hjälp av argumentet "Item[indexer]" för specifika indexerare (där indexeraren är indexvärdet) eller ett värde av "Item[]" för alla indexerare.
Du kan behandla en bindningskälla antingen som ett enskilt objekt vars egenskaper innehåller data eller som en samling objekt. I C#-kod kan du en gång binda till ett objekt som implementerar List<T> för att visa en samling som inte ändras vid körning. För en observerbar samling (observerar när objekt läggs till och tas bort från samlingen) binder envägsbindning till ObservableCollection<T> i stället. Om du vill binda till dina egna samlingsklasser använder du vägledningen i följande tabell.
| Scenario | C# (CLR) | C++/WinRT |
|---|---|---|
| Binda till ett objekt. | Kan vara valfritt objekt. | Kan vara valfritt objekt. |
| Hämta meddelanden om egenskapsändring från ett bundet objekt. | Objektet måste implementera INotifyPropertyChanged. | Objektet måste implementera INotifyPropertyChanged. |
| Binda till en samling. | Lista<T> | IVector för IInspectable eller IBindableObservableVector. Se XAML-objektkontroller; binda till en C++/WinRT-samling och samlingar med C++/WinRT. |
| Hämta meddelanden om samlingsändring från en bunden samling. | ObservableCollection<T> | IObservableVector av IInspectable. Till exempel winrt::single_threaded_observable_vector<T>. |
| Implementera en samling som stöder bindning. | Utöka list-T<> eller implementera IList-, IList-objekt<>, IEnumerable- eller IEnumerable-objekt<>. Bindning till generisk IList<T> och IEnumerable<T> stöds inte. |
Implementera IVector för IInspectable. Se XAML-objektkontroller; binda till en C++/WinRT-samling och samlingar med C++/WinRT. |
| Implementera en samling som stöder meddelanden om insamlingsändring. | Utöka ObservableCollection<T> eller implementera (icke-generisk) IList och INotifyCollectionChanged. | Implementera IObservableVector för IInspectable eller IBindableObservableVector. |
| Implementera en samling som stöder inkrementell inläsning. | Utöka ObservableCollection<T> eller implementera (icke-generisk) IList och INotifyCollectionChanged. Dessutom implementera ISupportIncrementalLoading. | Implementera IObservableVector för IInspectable eller IBindableObservableVector. Dessutom ska du implementera ISupportIncrementalLoading |
Du kan binda listkontroller till godtyckligt stora datakällor och fortfarande uppnå höga prestanda med hjälp av inkrementell inläsning. Du kan till exempel binda listkontroller till Bing-bildfrågeresultat utan att behöva läsa in alla resultat samtidigt. I stället läser du bara in vissa resultat omedelbart och läser in ytterligare resultat efter behov. Om du vill ha stöd för inkrementell inläsning måste du implementera ISupportIncrementalLoading på en datakälla som stöder meddelanden om insamlingsändringar. När databindningsmotorn begär mer data måste datakällan göra lämpliga begäranden, integrera resultaten och sedan skicka lämpliga meddelanden för att uppdatera användargränssnittet.
Bindningsmål
I följande två exempel är egenskapen Button.Content bindningsmålet. Dess värde är inställt på ett markeringstillägg som deklarerar bindningsobjektet. I det första exemplet visas {x:Bind}, och i det andra exemplet visas {Binding}. Att deklarera bindningar i markering är vanligt eftersom det är praktiskt, läsbart och lätt att använda. Men om du behöver kan du undvika markering och imperativt (programmatiskt) skapa en instans av klassen Bindning i stället.
<Button Content="{x:Bind ...}" ... />
<Button Content="{Binding ...}" ... />
Om du använder C++/WinRT måste du lägga till attributet BindableAttribute i valfri körningsklass som du vill använda {Binding} -markeringstillägget med.
Viktigt!
Om du använder C++/WinRT är attributet BindableAttribute tillgängligt med Windows App SDK. Utan det attributet måste du implementera gränssnitten ICustomPropertyProvider och ICustomProperty för att kunna använda markeringstillägget {Binding} .
Bindningsobjekt som deklarerats med {x:Bind}
Innan du skapar din {x:Bind} -markering måste du exponera din bindningskällaklass från klassen som representerar din sida med markering. Lägg till en egenskap (av typen HostViewModel i det här fallet) i din MainWindow fönsterklass.
namespace DataBindingInDepth
{
public sealed partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
ViewModel = new HostViewModel();
}
public HostViewModel ViewModel { get; set; }
}
}
När du har lagt till egenskapen kan du ta en närmare titt på markering som deklarerar bindningsobjektet. I följande exempel används samma Button.Content bindningsmål som du såg i avsnittet "Bindningsmål" tidigare. Den visar bindningsmålet HostViewModel.NextButtonText som är bundet till egenskapen.
<!-- MainWindow.xaml -->
<Window x:Class="DataBindingInDepth.MainWindow" ... >
<Button Content="{x:Bind Path=ViewModel.NextButtonText, Mode=OneWay}" ... />
</Window>
Observera värdet som du anger för Path. Fönstret tolkar det här värdet i sin egen kontext. I det här fallet börjar sökvägen med att referera till den ViewModel egenskap som du precis har lagt till på MainWindow sidan. Den egenskapen returnerar en HostViewModel instans, så att du kan pricka in i objektet för att komma åt HostViewModel.NextButtonText egenskapen. Du anger Mode för att åsidosätta standardvärdet {x:Bind} för en gång.
Egenskapen Path stöder en mängd olika syntaxalternativ för bindning till kapslade egenskaper, anslutna egenskaper samt heltals- och strängindexerare. Mer information finns i Syntax för egenskapssökväg. Bindning till strängindexerare ger dig effekten av bindning till dynamiska egenskaper utan att behöva implementera ICustomPropertyProvider. Andra inställningar finns i {x:Bind} markeringstillägg.
För att illustrera att egenskapen HostViewModel.NextButtonText är observerbar lägger du till en Click händelsehanterare på knappen och uppdaterar värdet HostViewModel.NextButtonTextför . Skapa, kör och klicka på knappen för att se värdet för knappens Content uppdatering.
// MainWindow.xaml.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
ViewModel.NextButtonText = "Updated Next button text";
}
Anmärkning
Ändringar i TextBox.Text skickas till en tvåvägsbunden källa när textrutan förlorar fokus och inte efter varje tangenttryckning.
DataTemplate och x:DataType
I en DataTemplate (om du använder den som en objektmall, en innehållsmall eller en rubrikmall) tolkas inte värdet Path för i fönstrets kontext. I stället fungerar det i kontexten för det dataobjekt som du skapar. När du använder {x:Bind} i en datamall kan du verifiera dess bindningar vid kompileringstid och generera effektiv kod för dem. För att göra detta måste DataTemplate deklarera typen av sitt dataobjekt med hjälp av x:DataType. Följande exempel kan användas som en objektkontroll som ItemTemplate är bunden till en samling 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>
Objekt med svag typ i sökvägen
Anta att du har en typ med namnet SampleDataGroup som implementerar en strängegenskap med namnet Title. Du har också en egenskap MainWindow.SampleDataGroupAsObject som är av typen object, men som faktiskt returnerar en instans av SampleDataGroup. Bindningen <TextBlock Text="{x:Bind SampleDataGroupAsObject.Title}"/> resulterar i ett kompileringsfel eftersom Title egenskapen inte hittas på typen object. Åtgärda det här felet genom att lägga till en cast i syntaxen Path så här: <TextBlock Text="{x:Bind ((data:SampleDataGroup)SampleDataGroupAsObject).Title}"/>. Här är ett annat exempel där Element deklareras som object men faktiskt är en TextBlock: <TextBlock Text="{x:Bind Element.Text}"/>. En typomvandling åtgärdar problemet: <TextBlock Text="{x:Bind ((TextBlock)Element).Text}"/>.
Om dina data läses in asynkront
De partiella klasserna för dina fönster genererar kod som stöd {x:Bind} vid kompilering. Du hittar dessa filer i mappen obj med namn som (för C#) <view name>.g.cs. Den genererade koden innehåller en hanterare för fönstrets inläsningshändelse . Den hanteraren anropar metoden Initialize på en genererad klass som representerar dina fönsterbindningar.
Initialize anrop Update för att börja flytta data mellan bindningskällan och målet.
Loading utlöses strax före det första måttpasset i fönstret eller användarkontrollen. Om dina data läses in asynkront kanske de inte är klara när de Initialize anropas. När du har läst in data kan du tvinga engångsbindningar att initieras genom att anropa this.Bindings.Update();. Om du bara behöver engångsbindningar för asynkront inlästa data är det mycket billigare att initiera dem på det här sättet än att ha enkelriktade bindningar och lyssna efter ändringar. Om dina data inte genomgår detaljerade ändringar och sannolikt kommer att uppdateras som en del av en specifik åtgärd kan du göra dina bindningar en gång och framtvinga en manuell uppdatering när som helst med ett anrop till Update.
Anmärkning
{x:Bind} passar inte för sena scenarier, till exempel navigering i ordlistestrukturen för ett JSON-objekt eller ankskrivning. "Anka skriver" är en svag form av att skriva baserat på lexikala matchningar på egenskapsnamn (som i , "om det går, simmar och kvacksalvare som en anka, då är det en anka"). Med ankskrivning skulle en bindning till Age egenskapen vara lika nöjd med ett Person eller ett Wine objekt (förutsatt att dessa typer var och en hade en Age egenskap). I dessa scenarier använder du markeringstillägget {Binding} .
Bindningsobjekt som deklareras med hjälp av {Binding}
Om du använder C++/WinRT lägger du till attributet BindableAttribute i valfri körningsklass som du vill binda till när du använder {Binding} -markeringstillägget. Om du vill använda {x:Bind} behöver du inte det attributet.
// HostViewModel.idl
// Add this attribute:
[Microsoft.UI.Xaml.Data.Bindable]
runtimeclass HostViewModel : Microsoft.UI.Xaml.Data.INotifyPropertyChanged
{
HostViewModel();
String NextButtonText;
}
Viktigt!
Om du använder C++/WinRT är attributet BindableAttribute tillgängligt med Windows App SDK. Utan det attributet måste du implementera gränssnitten ICustomPropertyProvider och ICustomProperty för att kunna använda markeringstillägget {Binding} .
Som standard förutsätter {Binding} att du binder till DataContext i markeringsfönstret.
DataContext Ange därför att fönstret ska vara en instans av din bindningskällklass (av typen HostViewModel i det här fallet). I följande exempel visas markering som deklarerar bindningsobjektet. Den använder samma Button.Content bindningsmål som användes i avsnittet "Bindningsmål" tidigare och binder till HostViewModel.NextButtonText egenskapen.
<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";
}
Observera värdet som angetts för Path. Fönstrets DataContext tolkar det här värdet, som i det här exemplet är inställt på en instans av HostViewModel. Sökvägen refererar till HostViewModel.NextButtonText egenskapen. Du kan utelämna Mode, eftersom standardvärdet {Binding} för enkelriktad fungerar här.
Standardvärdet för DataContext för ett användargränssnittselement är det ärvda värdet för dess överordnade element. Du kan uttryckligen åsidosätta den standardinställningen genom att sätta DataContext, vilket i sin tur ärvs av underordnade som standard. Att uttryckligen ange DataContext ett element är användbart när du vill ha flera bindningar som använder samma källa.
Ett bindningsobjekt har en Source egenskap som standard är DataContext för det användargränssnittselement som bindningen deklareras för. Du kan åsidosätta den här standardinställningen genom att ange Source, RelativeSourceeller ElementName uttryckligen på bindningen (se {Binding} för mer information).
I en DataTemplate anges DataContext automatiskt till det dataobjekt som mallas. Följande exempel kan användas som en objektkontroll som är bunden till en samling av vilken typ som helst som har strängegenskaper med namnen Title och Description.
<DataTemplate x:Key="SimpleItemTemplate">
<StackPanel Orientation="Vertical" Height="50">
<TextBlock Text="{Binding Title}"/>
<TextBlock Text="{Binding Description"/>
</StackPanel>
</DataTemplate>
Anmärkning
Som standard skickas ändringar i TextBox.Text till en tvåvägsbunden källa när textrutan förlorar fokus. Om du vill att ändringar ska skickas efter varje användarintryckning anger du UpdateSourceTrigger till PropertyChanged på bindningen i markering. Du kan också helt ta kontroll över när ändringar skickas till källan genom att ange UpdateSourceTrigger till Explicit. Sedan hanterar du händelser i textrutan (vanligtvis TextBox.TextChanged), anropar GetBindingExpression på målet för att hämta ett BindingExpression-objekt och anropar slutligen BindingExpression.UpdateSource för att programmatiskt uppdatera datakällan.
Egenskapen Path stöder en mängd olika syntaxalternativ för bindning till kapslade egenskaper, anslutna egenskaper samt heltals- och strängindexerare. Mer information finns i Syntax för egenskapssökväg. Bindning till strängindexerare ger dig effekten av bindning till dynamiska egenskaper utan att behöva implementera ICustomPropertyProvider. Egenskapen ElementName är användbar för element-till-element-bindning. Egenskapen RelativeSource har flera användningsområden, varav en är ett mer kraftfullt alternativ till mallbindning i ett ControlTemplate. Andra inställningar finns i {Binding}-markeringstillägget och klassen Bindning .
Vad händer om källan och målet inte är av samma typ?
Om du vill styra synligheten för ett användargränssnittselement baserat på värdet för en boolesk egenskap, eller om du vill återge ett gränssnittselement med en färg som är en funktion av ett numeriskt värdes intervall eller trend, eller om du vill visa ett datum- och/eller tidsvärde i en egenskap för användargränssnittselement som förväntar sig en sträng, måste du konvertera värden från en typ till en annan. Det finns fall där rätt lösning är att exponera en annan egenskap av rätt typ från din bindningskällklass och hålla konverteringslogik inkapslad och testbar där. Men den lösningen är inte flexibel eller skalbar när du har stora antal eller stora kombinationer av käll- och målegenskaper. I så fall har du ett par alternativ:
- Om du använder
{x:Bind}kan du binda direkt till en funktion för att göra den konverteringen - Eller så kan du ange en värdekonverterare som är ett objekt som är utformat för att utföra konverteringen
Värdekonverterare
Här är en värdekonverterare, lämplig för en engångsbindning eller en enkelriktad bindning, som konverterar ett DateTime-värde till ett string värde som innehåller månaden. Klassen implementerar 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();
}
}
Och så här använder du värdekonverteraren i din bindningsobjektmarkering.
<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}}"/>
Bindningsmotorn anropar metoderna Convert och ConvertBack om parametern Converter har definierats för bindningen. När data skickas från källan anropar Convert bindningsmotorn och skickar returnerade data till målet. När data skickas från målet (för en dubbelriktad bindning) anropar ConvertBack bindningsmotorn och skickar returnerade data till källan.
Konverteraren har också valfria parametrar: ConverterLanguage, som gör det möjligt att ange vilket språk som ska användas i konverteringen, och ConverterParameter, vilket gör det möjligt att skicka en parameter för konverteringslogik. Ett exempel som använder en konverterarparameter finns i IValueConverter.
Anmärkning
Om det finns ett fel i konverteringen ska du inte utlösa ett undantag. Returnera i stället DependencyProperty.UnsetValue, vilket stoppar dataöverföringen.
Om du vill visa ett standardvärde som ska användas när bindningskällan inte kan matchas anger du FallbackValue egenskapen för bindningsobjektet i markering. Detta är användbart för att hantera konverterings- och formateringsfel. Det är också användbart att binda till källegenskaper som kanske inte finns på alla objekt i en bunden samling heterogena typer.
Om du binder en textkontroll till ett värde som inte är en sträng konverterar databindningsmotorn värdet till en sträng. Om värdet är en referenstyp hämtar databindningsmotorn strängvärdet genom att anropa ICustomPropertyProvider.GetStringRepresentation eller IStringable.ToString om det är tillgängligt och anropar annars Object.ToString. Observera dock att bindningsmotorn ignorerar alla ToString implementeringar som döljer basklassimplementeringen. Underklassimplementeringar bör åsidosätta basklassmetoden ToString i stället. På samma sätt verkar alla hanterade objekt på interna språk implementera ICustomPropertyProvider och IStringable. Men alla anrop till GetStringRepresentation och IStringable.ToString dirigeras till Object.ToString eller åsidosätter den metoden och aldrig till en ny ToString implementering som döljer basklassimplementeringen.
Anmärkning
Windows Community Toolkit tillhandahåller en BoolToVisibilityConverter. Konverteraren mappar true till Visible uppräkningsvärdet och false till så att Collapsed du kan binda en Visibility egenskap till ett booleskt värde utan att skapa en konverterare. Om du vill använda konverteraren måste projektet lägga till NuGet-paketet CommunityToolkit.WinUI.Converters .
Funktionsbindning i {x:Bind}
{x:Bind} gör att det sista steget i en bindningssökväg kan vara en funktion. Använd den här funktionen för att utföra konverteringar eller för att skapa bindningar som är beroende av mer än en egenskap. Mer information finns i Funktioner i x:Bind.
Bindning mellan element
Du kan binda egenskapen för ett XAML-element till egenskapen för ett annat XAML-element. Här är ett exempel på hur bindningen ser ut i markup.
<TextBox x:Name="myTextBox" />
<TextBlock Text="{x:Bind myTextBox.Text, Mode=OneWay}" />
Resursordlistor med {x:Bind}
Markeringstillägget {x:Bind} är beroende av kodgenerering, så den behöver en kod bakom fil som innehåller en konstruktor som anropar InitializeComponent (för att initiera den genererade koden). Om du vill återanvända resursordlistan instansierar du dess typ (så att InitializeComponent anropas) i stället för att referera till dess filnamn. Här är ett exempel på vad du kan göra om du har en befintlig resursordlista och vill använda {x:Bind} den.
<!-- 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>
Blanda {x:Bind} och {Binding} i ett återanvändbart format
I föregående exempel visades hur du använder {x:Bind} i DataTemplates. Du kan också skapa återanvändbara formatmallar som kombinerar {x:Bind} och {Binding} markup-tillägg. Den här kombinationen är användbar när du vill binda vissa egenskaper till kompileringstid kända värden med hjälp av {x:Bind} och andra egenskaper till runtime DataContext-värden med hjälp av {Binding}.
I följande exempel visas hur du skapar ett återanvändbart knappformat som använder båda bindningsmetoderna:
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);
}
}
Användning i MainWindow.xaml med en ViewModel som tillhandahåller körningsvärden:
<!-- 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 som tillhandahåller körningsbindningsvärden):
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;
}
}
I det här exemplet:
-
{Binding}används för egenskaper som är beroende av DataContext (ButtonBackgroundBrush, ButtonForegroundBrush, ButtonHoverBrush) -
{x:Bind}används för egenskaper som är kända för kompileringstid och tillhör själva ResourceDictionary (DefaultIndicatorBrush, DefaultPressedBrush) - Formatet kan återanvändas och du kan använda det på valfri knapp
- Körningstema är möjligt via DataContext och drar fortfarande nytta av
{x:Bind}prestanda för statiska element
Händelsebindning och ICommand
{x:Bind} stöder en funktion som kallas händelsebindning. Med den här funktionen kan du ange hanteraren för en händelse med hjälp av en bindning. Den här funktionen är ytterligare ett alternativ för att hantera händelser, utöver att hantera händelser med en metod i filen bakom koden. Anta att du har en ListViewDoubleTapped händelsehanterare i klassen MainWindow .
public sealed partial class MainWindow : Window
{
...
public void ListViewDoubleTapped()
{
// Handle double-tapped logic
}
}
Du kan binda en DoubleTapped-händelse i ListView till en metod i MainWindow så här.
<ListView DoubleTapped="{x:Bind ListViewDoubleTapped}" />
Du kan inte använda överlagrade metoder för att hantera en händelse med den här tekniken. Om metoden som hanterar händelsen också har parametrar, måste alla parametrar vara respektive tilldelningsbara från typerna av händelsens alla parametrar. I det här fallet ListViewDoubleTapped är inte överbelastad och har inga parametrar (men det skulle fortfarande vara giltigt även om det tog två object parametrar).
Händelsebindningstekniken liknar implementering och användning av kommandon. Ett kommando är en egenskap som returnerar ett objekt som implementerar ICommand-gränssnittet . Både {x:Bind} och {Binding} fungerar med kommandon. Så att du inte behöver implementera kommandomönstret flera gånger kan du använda hjälpklassen DelegateCommand som du hittar i QuizGame UWP-exemplet (i mappen "Common").
Bindning till en samling mappar eller filer
Du kan använda API:erna i namnområdet Windows.Storage för att hämta mapp- och fildata i dina paketerade Windows App SDK-appar. De olika GetFilesAsyncmetoderna , GetFoldersAsyncoch GetItemsAsync returnerar dock inte värden som är lämpliga för bindning till listkontroller. I stället måste du binda till returvärdena för metoderna GetVirtualizedFilesVector, GetVirtualizedFoldersVector och GetVirtualizedItemsVector i klassen FileInformationFactory . Följande kodexempel från UWP-exemplet StorageDataSource och GetVirtualizedFilesVector visar det typiska användningsmönstret. Kom ihåg att deklarera funktionen picturesLibrary i apppaketmanifestet och bekräfta att det finns bilder i biblioteksmappen Bilder.
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;
}
Du använder vanligtvis den här metoden för att skapa en skrivskyddad vy över fil- och mappinformation. Du kan skapa tvåvägsbindningar till fil- och mappegenskaperna, till exempel för att låta användare betygsätta en låt i en musikvy. Ändringar sparas dock inte förrän du anropar lämplig SavePropertiesAsync metod (till exempel MusicProperties.SavePropertiesAsync). Du bör committa ändringar när objektet förlorar fokus eftersom denna åtgärd utlöser en återställning av markeringen.
Observera att dubbelriktad bindning med den här tekniken endast fungerar med indexerade platser, till exempel Musik. Du kan avgöra om en plats indexeras genom att anropa metoden FolderInformation.GetIndexedStateAsync .
Observera också att en virtualiserad vektor kan returneras null för vissa objekt innan den fyller i deras värde. Du bör till exempel söka efter innan du använder värdet null för en listkontroll som är bunden till en virtualiserad vektor, eller använd SelectedIndex i stället.
Bindning till data grupperade efter en nyckel
Om du tar en platt samling objekt (böcker, till exempel representeras av en BookSku klass) och du grupperar objekten med hjälp av en gemensam egenskap som en nyckel ( BookSku.AuthorName egenskapen, till exempel), kallas resultatet grupperade data. När du grupperar data är det inte längre en platt samling. Grupperade data är en samling gruppobjekt, där varje gruppobjekt har:
- en nyckel, och
- en samling objekt vars egenskap matchar den nyckeln.
Om du vill ta bokexemplet igen resulterar resultatet av att gruppera böckerna efter författarens namn i en samling med författarnamnsgrupper där varje grupp har:
- en nyckel, som är ett författarens namn, och
- en samling av de
BookSkuobjekt varsAuthorNameegenskap matchar gruppens nyckel.
Om du vill visa en samling binder du objektkällan för en objektkontroll (till exempel ListView eller GridView) direkt till en egenskap som returnerar en samling. Om det är en platt samling objekt behöver du inte göra något speciellt. Men om det är en samling gruppobjekt (som när du binder till grupperade data) behöver du tjänsterna för ett mellanliggande objekt som kallas CollectionViewSource som finns mellan objektkontrollen och bindningskällan. Du binder CollectionViewSource till egenskapen som returnerar grupperade data och binder objektkontrollen till CollectionViewSource. Ett extra värdetillägg av ett CollectionViewSource är att det håller reda på det aktuella objektet, så att du kan hålla fler än ett objekt i synkronisering genom att binda dem alla till samma CollectionViewSource. Du kan också komma åt det aktuella objektet programmatiskt via egenskapen ICollectionView.CurrentItem för objektet som returneras av egenskapen CollectionViewSource.View .
Om du vill aktivera grupperingsanläggningen för en CollectionViewSource anger du IsSourceGrouped till true. Om du också behöver ange egenskapen ItemsPath beror på exakt hur du skapar dina gruppobjekt. Det finns två sätt att skapa ett gruppobjekt: mönstret "is-a-group" och mönstret "has-a-group". I mönstret "is-a-group" härleds gruppobjektet från en samlingstyp (till exempel List<T>), så gruppobjektet är faktiskt själva objektgruppen. Med det här mönstret behöver du inte ange ItemsPath. I mönstret "has-a-group" har gruppobjektet en eller flera egenskaper av en samlingstyp (till exempel List<T>), så gruppen "har en" grupp med objekt i form av en egenskap (eller flera grupper av objekt i form av flera egenskaper). Med det här mönstret måste du ange ItemsPath namnet på egenskapen som innehåller objektgruppen.
I följande exempel visas mönstret "has-a-group". Fönsterklassen har en egenskap med namnet DataContext, som returnerar en instans av vår vymodell.
CollectionViewSource binder till Authors egenskapen för vymodellen (Authors är samlingen med gruppobjekt) och anger även att det är egenskapen Author.BookSkus som innehåller de grupperade objekten. Slutligen är GridView bundet CollectionViewSourcetill , och dess gruppformat har definierats så att det kan återge objekten i grupper.
<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>
Du kan implementera mönstret "is-a-group" på något av två sätt. Ett sätt är att skapa en egen gruppklass. Härled klassen från List<T> (där T är typen av objekt). Till exempel public class Author : List<BookSku>. Det andra sättet är att använda ett LINQ-uttryck för att dynamiskt skapa gruppobjekt (och en gruppklass) från liknande egenskapsvärden för BookSku-objekten . Den här metoden – att endast underhålla en platt lista över objekt och gruppera dem i farten – är typisk för en app som kommer åt data från en molntjänst. Du får flexibiliteten att gruppera böcker efter författare eller genre (till exempel) utan att behöva särskilda gruppklasser som Författare och Genre.
I följande exempel visas "is-a-group"-mönstret med LINQ. Den här gången grupperar vi böcker efter genre, som visas med genrenamnet i grupprubrikerna. Den här grupperingen indikeras av egenskapen "Nyckel" med hänvisning till gruppNyckel-värdet.
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;
}
}
Kom ihåg att när du använder {x:Bind} med datamallar måste du ange vilken typ som ska bindas till genom att ange ett x:DataType värde. Om typen är allmän kan du inte uttrycka den i markering, så du måste använda {Binding} i stället i mallen för gruppformatrubriken.
<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>
En SemanticZoom-kontroll är ett bra sätt för användarna att visa och navigera i grupperade data.
Exempelappen Bookstore2 UWP visar hur du SemanticZoomanvänder . I appen kan du visa en lista över böcker grupperade efter författare (den inzoomade vyn) eller så kan du zooma ut för att se en snabblista med författare (den utzoomade vyn). Hopplistan ger mycket snabbare navigering än att bläddra igenom listan över böcker. De inzoomade och utzoomade vyerna är faktiskt ListView eller GridView kontroller som är bundna till samma CollectionViewSource.
När du binder till hierarkiska data, till exempel underkategorier inom kategorier, kan du välja att visa hierarkiska nivåer i användargränssnittet med en serie objektkontroller. En markering i en objektkontroll avgör innehållet i efterföljande objektkontroller. Du kan hålla listorna synkroniserade genom att binda varje lista till sin egen CollectionViewSource och binda CollectionViewSource samman instanserna i en kedja. Den här konfigurationen kallas för en huvud/detaljvy (eller lista/detaljvy). Mer information finns i Så här binder du till hierarkiska data och skapar en huvud-/informationsvy.
Diagnostisera och felsöka problem med databindning
Bindningsmarkeringen innehåller namnen på egenskaperna (och för C#, ibland fält och metoder). Så när du byter namn på en egenskap måste du också ändra alla bindningar som refererar till den. Om du glömmer att göra det skapar du en databindningsfel och appen kompilerar inte eller körs inte korrekt.
Bindningsobjekten som {x:Bind} och {Binding} skapar är till stor del funktionellt likvärdiga. Men {x:Bind} har typinformation för bindningskällan och genererar källkod vid kompileringstillfället. Med {x:Bind}får du samma typ av problemidentifiering som du får med resten av koden. Den identifieringen omfattar kompileringstidsverifiering av dina bindningsuttryck och felsökning genom att ange brytpunkter i källkoden som genereras som partiell klass för sidan. Du hittar dessa klasser i filerna i mappen obj med namn som (för C#) <view name>.g.cs). Om du har problem med en bindning aktiverar du Bryt vid ohanterade undantag i Microsoft Visual Studio-felsökningsprogrammet. Felsökningsprogrammet bryter körningen vid den tidpunkten, och du kan sedan felsöka vad som gick fel. Koden som genereras av {x:Bind} följer samma mönster för varje del av grafen med bindning av källnoder, och du kan använda informationen i fönstret Anropa stack för att fastställa sekvensen av anrop som ledde fram till problemet.
{Binding} har ingen typinformation för bindningskällan. Men när du kör din app med felsökningsprogrammet kopplat visas eventuella bindningsfel i fönstret Utdata - och XAML-bindningsfel i Visual Studio. Mer information om felsökning av bindningsfel i Visual Studio finns i XAML-databindningsdiagnostik.
Skapa bindningar i kod
Anmärkning
Det här avsnittet gäller endast för {Binding}, eftersom du inte kan skapa {x:Bind} -bindningar i kod. Du kan dock uppnå några av samma fördelar {x:Bind} med DependencyObject.RegisterPropertyChangedCallback, vilket gör att du kan registrera dig för ändringsmeddelanden för alla beroendeegenskaper.
Du kan också ansluta gränssnittselement till data med hjälp av procedurkod i stället för XAML. Det gör du genom att skapa ett nytt bindningsobjekt , ange lämpliga egenskaper och sedan anropa FrameworkElement.SetBinding eller BindingOperations.SetBinding. Att skapa bindningar programmatiskt är användbart när du vill välja bindningsegenskapsvärdena vid körning eller dela en enda bindning mellan flera kontroller. Du kan dock inte ändra bindningsegenskapsvärdena när du anropar SetBinding.
I följande exempel visas hur du implementerar en bindning i kod.
<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);
Funktionsjämförelse för {x:Bind} och {Binding}
| Egenskap | {x:Bind} jämfört med {Binding} | Noteringar |
|---|---|---|
| Sökvägen är standardegenskapen | {x:Bind a.b.c}- {Binding a.b.c} |
|
| Sökvägsegenskap | {x:Bind Path=a.b.c}- {Binding Path=a.b.c} |
x:Bind I Pathrotas i fönstret som standard, inte i DataContext. |
| Indexer | {x:Bind Groups[2].Title}- {Binding Groups[2].Title} |
Binder till det angivna objektet i samlingen. Endast heltalsbaserade index stöds. |
| Anslutna egenskaper | {x:Bind Button22.(Grid.Row)}- {Binding Button22.(Grid.Row)} |
Anslutna egenskaper anges med parenteser. Om egenskapen inte deklareras i ett XAML-namnområde prefixar du den med ett XML-namnområde, som ska mappas till ett kodnamnområde i dokumentets huvud. |
| Gjutning | {x:Bind groups[0].(data:SampleDataGroup.Title)}- Behövs inte för {Binding}. |
Casts anges med parenteser. Om egenskapen inte deklareras i ett XAML-namnområde prefixar du den med ett XML-namnområde, som ska mappas till ett kodnamnområde i dokumentets huvud. |
| Omvandlare | {x:Bind IsShown, Converter={StaticResource BoolToVisibility}}- {Binding IsShown, Converter={StaticResource BoolToVisibility}} |
Deklarera konverterare vid roten i fönstret, kontrollen, resursordboken eller i 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} |
Deklarera konverterare i roten av Window, Control, ResourceDictionary eller i App.xaml. |
| TargetNullValue | {x:Bind Name, TargetNullValue=0}- {Binding Name, TargetNullValue=0} |
Används när bladet i bindningsuttrycket är null. Använd enkla citattecken för ett strängvärde. |
| FallbackValue | {x:Bind Name, FallbackValue='empty'}- {Binding Name, FallbackValue='empty'} |
Används när någon del av sökvägen för bindningen (förutom bladet) är null. |
| ElementName | {x:Bind slider1.Value}- {Binding Value, ElementName=slider1} |
Med {x:Bind} binder du till ett fält; Path är som standard rotat i fönstret, vilket betyder att du kan komma åt alla namngivna element via dess fält. |
| RelativeSource: Själv | <Rectangle x:Name="rect1" Width="200" Height="{x:Bind rect1.Width}" ... />- <Rectangle Width="200" Height="{Binding Width, RelativeSource={RelativeSource Self}}" ... /> |
Med {x:Bind}namnger du elementet och använder dess namn i Path. |
| RelativeSource: TemplatedParent | Behövs inte för {x:Bind}- {Binding <path>, RelativeSource={RelativeSource TemplatedParent}} |
Med {x:Bind}anger on TargetTypeControlTemplate bindning till mallens överordnade. För {Binding}kan vanlig mallbindning användas i kontrollmallar för de flesta användningsområden. Men använd TemplatedParent där du behöver använda en konverterare eller en dubbelriktad bindning. |
| Källa | Behövs inte för {x:Bind}- <ListView ItemsSource="{Binding Orders, Source={StaticResource MyData}}"/> |
För {x:Bind} du kan använda det namngivna elementet direkt, använda en egenskap eller en statisk sökväg. |
| Mode | {x:Bind Name, Mode=OneWay}- {Binding Name, Mode=TwoWay} |
Mode kan vara OneTime, OneWayeller TwoWay.
{x:Bind} standardvärdet är OneTime; {Binding} standardvärdet OneWay. |
| UpdateSourceTrigger | {x:Bind Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}- {Binding UpdateSourceTrigger=PropertyChanged} |
UpdateSourceTrigger kan vara Default, LostFocuseller PropertyChanged.
{x:Bind} stöder inte UpdateSourceTrigger=Explicit.
{x:Bind} använder PropertyChanged beteende för alla fall utom TextBox.Text, där det använder LostFocus beteende. |
Se även
Windows developer