Gecompileerde bindingen
Gegevensbindingen voor .NET Multi-Platform App UI (.NET MAUI) hebben twee belangrijke problemen:
- Er is geen compileertijdvalidatie van bindingexpressies. In plaats daarvan worden bindingen tijdens runtime opgelost. Daarom worden ongeldige bindingen pas gedetecteerd als runtime wanneer de toepassing zich niet gedraagt zoals verwacht of foutberichten worden weergegeven.
- Ze zijn niet kostenefficiënt. Bindingen worden tijdens runtime opgelost met behulp van objectinspectie voor algemeen gebruik (reflectie) en de overhead hiervoor verschilt van platform tot platform.
Gecompileerde bindingen verbeteren de prestaties van gegevensbindingen in .NET MAUI-toepassingen door bindingexpressies tijdens het compileren op te lossen in plaats van runtime. Bovendien biedt deze compileertijdvalidatie van bindingexpressies een betere ervaring voor probleemoplossing voor ontwikkelaars omdat ongeldige bindingen worden gerapporteerd als buildfouten.
Belangrijk
Gecompileerde bindingen zijn vereist in plaats van bindingen op basis van tekenreeksen in NativeAOT-apps en in apps waarvoor volledig bijsnijden is ingeschakeld. Zie voor meer informatie Trim a .NET MAUI app en Native AOT deployment.
Gecompileerde bindingen in XAML
Als u gecompileerde bindingen in XAML wilt gebruiken, stelt u een x:DataType
kenmerk in op een VisualElement op het type object waaraan de VisualElement en de onderliggende items worden gekoppeld. Het is raadzaam om het kenmerk x:DataType
in te stellen op hetzelfde niveau in de weergavehiërarchie als de BindingContext is ingesteld. Dit kenmerk kan echter opnieuw worden gedefinieerd op elke locatie in een weergavehiërarchie.
Belangrijk
Voor gecompileerde bindingen is het gebruik van XAML-compilatie vereist. Deze is standaard ingeschakeld in .NET MAUI. Als u XAML-compilatie hebt uitgeschakeld, moet u deze inschakelen. Zie XAML-compilatievoor meer informatie.
Als u gecompileerde bindingen in XAML wilt gebruiken, moet het kenmerk x:DataType
worden ingesteld op een letterlijke tekenreeks of een type met behulp van de x:Type
markeringsextensie. Tijdens het compileren van XAML worden ongeldige bindingexpressies gerapporteerd als buildfouten. De XAML-compiler rapporteert echter alleen een buildfout voor de eerste ongeldige bindingsexpressie die deze tegenkomt. Geldige bindingexpressies die zijn gedefinieerd voor de VisualElement of zijn onderliggende elementen, worden gecompileerd, ongeacht of de BindingContext is ingesteld in XAML of code. Bij het compileren van een bindingsexpressie wordt gecompileerde code gegenereerd die een waarde ophaalt uit een eigenschap op de bron-en deze instelt op de eigenschap op de doel- die is opgegeven in de markering. Afhankelijk van de bindingsexpressie kan de gegenereerde code bovendien wijzigingen in de waarde van de eigenschap bron observeren en de eigenschap doel vernieuwen, en kan wijzigingen van het doel terug naar de bronpushen.
Belangrijk
Gecompileerde bindingen zijn uitgeschakeld voor XAML-bindingexpressies die de eigenschap Source
definiëren. Dit komt doordat de eigenschap Source
altijd is ingesteld met behulp van de x:Reference
markeringsextensie, die niet kan worden omgezet tijdens het compileren.
Bovendien worden gecompileerde bindingen in XAML momenteel niet ondersteund op meerdere bindingen.
.NET MAUI produceert standaard geen buildwaarschuwingen voor XAML-bindingen die geen gecompileerde bindingen gebruiken. U kunt echter kiezen voor gecompileerde bindingswaarschuwingen die worden gegenereerd door de eigenschap $(MauiStrictXamlCompilation)
build in te stellen op true
in het projectbestand van uw app (*.csproj):
<MauiStrictXamlCompilation>true</MauiStrictXamlCompilation>
.NET MAUI produceert standaard buildwaarschuwingen voor XAML-bindingen die geen gecompileerde bindingen gebruiken.
Voor meer informatie over waarschuwingen voor gecompileerde XAML-bindingen, zie .
Gecompileerde bindingen gebruiken in XAML
In het volgende voorbeeld ziet u hoe u gecompileerde bindingen gebruikt tussen .NET MAUI-weergaven en viewmodel-eigenschappen:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataBindingDemos"
x:Class="DataBindingDemos.CompiledColorSelectorPage"
x:DataType="local:HslColorViewModel"
Title="Compiled Color Selector">
<ContentPage.BindingContext>
<local:HslColorViewModel Color="Sienna" />
</ContentPage.BindingContext>
...
<StackLayout>
<BoxView Color="{Binding Color}"
... />
<StackLayout Margin="10, 0">
<Label Text="{Binding Name}" />
<Slider Value="{Binding Hue}" />
<Label Text="{Binding Hue, StringFormat='Hue = {0:F2}'}" />
<Slider Value="{Binding Saturation}" />
<Label Text="{Binding Saturation, StringFormat='Saturation = {0:F2}'}" />
<Slider Value="{Binding Luminosity}" />
<Label Text="{Binding Luminosity, StringFormat='Luminosity = {0:F2}'}" />
</StackLayout>
</StackLayout>
</ContentPage>
De ContentPage instantieert de HslColorViewModel
en initialiseert de eigenschap Color
binnen eigenschapselementtags voor de eigenschap BindingContext. De ContentPage definieert ook het kenmerk x:DataType
als het viewmodel-type, waarmee wordt aangegeven dat bindingexpressies in de ContentPage weergavehiërarchie worden gecompileerd. Dit kan worden gecontroleerd door een van de bindingexpressies te wijzigen om te binden aan een niet-bestaande viewmodel-eigenschap, wat resulteert in een buildfout. Hoewel in dit voorbeeld het kenmerk x:DataType
wordt ingesteld op een letterlijke tekenreeks, kan het ook worden ingesteld op een type met de x:Type
markeringsextensie. Zie x:Type
voor meer informatie over de markeringsextensie.
Belangrijk
Het kenmerk x:DataType
kan op elk moment in een weergavehiërarchie opnieuw worden gedefinieerd.
De BoxView- en Label-elementen en Slider weergaven nemen de bindingscontext over van de ContentPage. Deze weergaven zijn allemaal bindingsdoelen die verwijzen naar broneigenschappen in het viewmodel. Voor de eigenschap BoxView.Color
en de eigenschap Label.Text
worden de gegevensbindingen OneWay
. De eigenschappen in de weergave worden ingesteld vanuit de eigenschappen in het viewmodel. De eigenschap Slider.Value
maakt echter gebruik van een TwoWay
binding. Hierdoor kan elke Slider worden ingesteld vanuit het viewmodel en kan het viewmodel ook worden ingesteld vanuit elke Slider.
Wanneer het voorbeeld voor het eerst wordt uitgevoerd, worden de BoxView, Label elementen en Slider elementen allemaal ingesteld vanuit het viewmodel op basis van de initiële eigenschap Color
ingesteld toen het viewmodel werd geïnstantieerd. Terwijl de schuifregelaars worden bewerkt, worden de BoxView- en Label-elementen dienovereenkomstig bijgewerkt:
Voor meer informatie over deze kleurkiezer, zie ViewModels en meldingen van eigenschapswijzigingen.
Gecompileerde bindingen gebruiken in XAML in een DataTemplate
Bindingen in een DataTemplate worden geïnterpreteerd in de context van het object dat wordt gesjabloond. Wanneer u gecompileerde bindingen in een DataTemplategebruikt, moet de DataTemplate daarom het type gegevensobject declareren met behulp van het kenmerk x:DataType
. Als dit niet gebeurt, kan dit ertoe leiden dat de DataTemplate een onjuiste x:DataType
overneemt van de bovenliggende scope.
<ContentPage ...
x:DataType="local:AnimalsPageViewModel">
<!-- Binding to AnimalsPageViewModel.Animals -->
<CollectionView ItemsSource="{Binding Animals}">
<CollectionView.ItemTemplate>
<DataTemplate>
<!-- incorrect: compiler thinks you want to bind to AnimalsPageViewModel.Name -->
<Label Text="{Binding Name}" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</ContentPage>
In het volgende voorbeeld ziet u hoe u de x:DataType
correct instelt op een DataTemplate:
<ContentPage ...
x:DataType="local:AnimalsPageViewModel">
<!-- Binding to AnimalsPageViewModel.Animals -->
<CollectionView ItemsSource="{Binding Animals}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="local:Animal">
<!-- correct: compiler knows you want to bind to Animal.Name -->
<Label Text="{Binding Name}" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</ContentPage>
Hoewel in dit voorbeeld het kenmerk x:DataType
wordt ingesteld op een letterlijke tekenreeks, kan het ook worden ingesteld op een type met de x:Type
markeringsextensie. Zie x:Type
voor meer informatie over de markeringsextensie.
Bindingen compileren die een algemeen type opgeven
Algemene typen kunnen worden opgegeven met het kenmerk x:DataType
door de algemene beperking op te geven als een voorvoegseltekenreeksargument tussen haakjes:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyMauiApp"
x:Class="MyMauiApp.MyPage"
x:DataType="local:MyViewModel(x:Boolean)">
...
</ContentPage>
Meerdere typeargumenten kunnen worden opgegeven als voorvoegseltekenreeksargumenten, gescheiden door een komma:
<DataTemplate x:DataType="local:MyType(local:MyObject,x:Boolean)">
...
</DataTemplate>
Zie Genericsvoor meer informatie over generics in XAML.
Bindingen compileren die de eigenschap Source
definiëren
Vóór .NET MAUI 9 slaat de XAML-compiler de compilatie van bindingen over die de eigenschap Source
definiëren in plaats van de BindingContext. Vanaf .NET MAUI 9 kunnen deze bindingen worden gecompileerd om te profiteren van betere runtimeprestaties. Deze optimalisatie is echter niet standaard ingeschakeld om te voorkomen dat bestaande app-code wordt onderbroken. Als u deze optimalisatie wilt inschakelen, stelt u de eigenschap $(MauiEnableXamlCBindingWithSourceCompilation)
build in op true
in het projectbestand van uw app:
<MauiEnableXamlCBindingWithSourceCompilation>true</MauiEnableXamlCBindingWithSourceCompilation>
Zorg er vervolgens voor dat al uw bindingen worden geannoteerd met de juiste x:DataType
en dat ze geen onjuiste gegevenstypen overnemen van het bovenliggende bereik:
<HorizontalStackLayout BindingContext="{x:Reference slider}" x:DataType="Slider">
<Label Text="{Binding Value}" />
<Label Text="{Binding Text, Source={x:Reference entry}, x:DataType=Entry}" />
</HorizontalStackLayout>
Notitie
In gevallen waarin er een binding is met een Source
, maar de x:DataType
van het bovenliggende item wordt overgenomen, kan er een verschil zijn tussen de x:DataType
en het type van de Source
. In dit scenario wordt er een waarschuwing gegenereerd en wordt er teruggevallen op een binding gebaseerd op reflectie, die het bindingspad tijdens de uitvoeringstijd oplost.
Gecompileerde bindingen combineren met klassieke bindingen in XAML
Bindingexpressies worden alleen gecompileerd voor de weergavehiërarchie waarop het kenmerk x:DataType
is gedefinieerd. Omgekeerd zullen weergaven in een hiërarchie, waarop het kenmerk x:DataType
niet is gedefinieerd, klassieke bindingen gebruiken. Het is daarom mogelijk om gecompileerde bindingen en klassieke bindingen op een pagina te combineren. In de vorige sectie gebruiken de weergaven in de DataTemplate gecompileerde bindingen, terwijl de BoxView, die is ingesteld op de kleur geselecteerd in de ListView, dat niet doet.
Het zorgvuldig structureren van x:DataType
kenmerken kan daarom leiden tot een pagina met behulp van gecompileerde en klassieke bindingen. Het kenmerk x:DataType
kan ook op elk moment in een weergavehiërarchie opnieuw worden gedefinieerd naar null
met behulp van de x:Null
markup-extensie. Dit geeft aan dat alle bindingsexpressies binnen de kijkhiërarchie klassieke bindingsmethoden gebruiken. In het volgende voorbeeld ziet u deze aanpak:
<StackLayout x:DataType="local:HslColorViewModel">
<StackLayout.BindingContext>
<local:HslColorViewModel Color="Sienna" />
</StackLayout.BindingContext>
<BoxView Color="{Binding Color}"
VerticalOptions="FillAndExpand" />
<StackLayout x:DataType="{x:Null}"
Margin="10, 0">
<Label Text="{Binding Name}" />
<Slider Value="{Binding Hue}" />
<Label Text="{Binding Hue, StringFormat='Hue = {0:F2}'}" />
<Slider Value="{Binding Saturation}" />
<Label Text="{Binding Saturation, StringFormat='Saturation = {0:F2}'}" />
<Slider Value="{Binding Luminosity}" />
<Label Text="{Binding Luminosity, StringFormat='Luminosity = {0:F2}'}" />
</StackLayout>
</StackLayout>
De basis-StackLayout stelt het x:DataType
attribuut in op het HslColorViewModel
type, wat aangeeft dat een koppelingsexpressie in de basis-StackLayout weergavehiërarchie wordt gecompileerd. De binnenste StackLayout herdefinieert het x:DataType
-attribuut naar null
met de x:Null
-markup-expressie. Daarom gebruiken de bindingexpressies in de binnenste StackLayout klassieke bindingen. Alleen de BoxViewin de hoofd-StackLayout weergavehiërarchie maakt gebruik van gecompileerde bindingen.
Voor meer informatie over de x:Null
-opmaakexpressie, zie x:Null-markeringsextensie.
Waarschuwingen voor gecompileerde XAML-bindingen
De volgende tabel bevat de compilerwaarschuwingen voor gecompileerde bindingen en hoe u deze kunt oplossen:
Code | Bericht | Repareren |
---|---|---|
XC0022 |
Binding kan worden gecompileerd om de runtimeprestaties te verbeteren als x:DataType is opgegeven. |
Voeg x:DataType toe aan uw XAML om het type van de huidige BindingContextop te geven. Het is raadzaam om x:DataType toe te voegen aan alle elementen waarin de bindingscontext verandert. |
XC0023 |
Binding kan worden gecompileerd om de runtime-prestaties te verbeteren als x:DataType niet expliciet null . |
Vervang x:DataType="{x:Null}" door het juiste type. |
Code | Bericht |
---|---|
XC0022 |
Binding kan worden gecompileerd om de runtimeprestaties te verbeteren als x:DataType is opgegeven. Als u deze waarschuwing wilt oplossen, voegt u x:DataType toe aan uw XAML om het type van de huidige BindingContextop te geven. Het is raadzaam om x:DataType toe te voegen aan alle elementen waarin de bindingscontext verandert. |
XC0023 |
Binding kan worden gecompileerd om de runtime-prestaties te verbeteren als x:DataType niet expliciet null . Als u deze waarschuwing wilt oplossen, vervangt u x:DataType="{x:Null}" door het juiste type. |
XC0024 |
Binding kan onjuist worden gecompileerd omdat de x:DataType annotatie afkomstig is van buiten een groter bereik. Zorg ervoor dat u alle DataTemplate XAML-elementen annoteert met de juiste x:DataType . Als u deze waarschuwing wilt oplossen, moet u ervoor zorgen dat alle DataTemplate elementen worden geannoteerd met de juiste x:DataType . |
XC0025 |
Binding is niet gecompileerd omdat het een expliciete Source -eigenschap heeft en de compilatie van bindingen met Source niet is ingeschakeld. Overweeg deze optimalisatie in te schakelen door de <MauiEnableXamlCBindingWithSourceCompilation>true</MauiEnableXamlCBindingWithSourceCompilation> in uw projectbestand in te stellen en ervoor te zorgen dat de juiste x:DataType is opgegeven voor deze binding. U kunt deze waarschuwing oplossen door de eigenschap $(MauiEnableXamlCBindingWithSourceCompilation) build in uw projectbestand in te schakelen en aantekeningen te maken op al uw bindingen met de juiste x:DataType . |
Als u ervoor wilt zorgen dat deze waarschuwingen niet worden genegeerd, kunt u specifieke waarschuwingen wijzigen om fouten te maken met de eigenschap $(WarningsAsErrors)
build:
<WarningsAsErrors>$(WarningsAsErrors);XC0022;XC0023</WarningsAsErrors>
Als u deze waarschuwingen wilt negeren, gebruikt u de eigenschap $(NoWarn)
build met specifieke waarschuwingscodes:
<NoWarn>$(NoWarn);XC0022;XC0023</NoWarn>
Belangrijk
XC0022
en XC0023
waarschuwingen worden altijd onderdrukt, tenzij de eigenschap $(MauiStrictXamlCompilation)
build is ingesteld op true
.
Als u de eigenschap $(TreatWarningsAsErrors)
build instelt op true
in het projectbestand van uw app, maar u bepaalde XAML-compilerwaarschuwingen wilt negeren, gebruikt u de eigenschap $(NoWarn)
build om deze waarschuwingen stil te leggen of de eigenschap $(WarningsNotAsErrors)
build om de ernst van bepaalde specifieke codes te verminderen.
.NET MAUI produceert standaard buildwaarschuwingen voor XAML-bindingen die geen gecompileerde bindingen gebruiken. U kunt kiezen voor gecompileerde bindingswaarschuwingen die als fouten worden behandeld door de eigenschappen van de $(MauiStrictXamlCompilation)
en $(TreatWarningsAsErrors)
build in te stellen op true
in het projectbestand van uw app (*.csproj):
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<MauiStrictXamlCompilation>true</MauiStrictXamlCompilation>
Notitie
De build-eigenschap $(MauiStrictXamlCompilation)
is standaard false
, tenzij u uw app publiceert door volledig trimmen of NativeAOT te gebruiken.
Gecompileerde bindingen in code
Bindingen die in code zijn geschreven, maken doorgaans gebruik van tekenreekspaden die tijdens runtime worden opgelost met weerspiegeling. De SetBinding-extensiemethode heeft echter ook een overbelasting die bindingen definieert met behulp van een Func
argument in plaats van een tekenreekspad:
MyLabel.SetBinding(Label.TextProperty, static (Entry entry) => entry.Text);
Niet alle methoden kunnen worden gebruikt om een gecompileerde binding te definiëren. De expressie moet een eenvoudige expressie voor toegang tot eigenschappen zijn. In de volgende voorbeelden worden geldige en ongeldige bindingexpressies weergegeven:
// Valid: Property access
static (PersonViewModel vm) => vm.Name;
static (PersonViewModel vm) => vm.Address?.Street;
// Valid: Array and indexer access
static (PersonViewModel vm) => vm.PhoneNumbers[0];
static (PersonViewModel vm) => vm.Config["Font"];
// Valid: Casts
static (Label label) => (label.BindingContext as PersonViewModel).Name;
static (Label label) => ((PersonViewModel)label.BindingContext).Name;
// Invalid: Method calls
static (PersonViewModel vm) => vm.GetAddress();
static (PersonViewModel vm) => vm.Address?.ToString();
// Invalid: Complex expressions
static (PersonViewModel vm) => vm.Address?.Street + " " + vm.Address?.City;
static (PersonViewModel vm) => $"Name: {vm.Name}";
Waarschuwing
Er treedt een CS0272-compilerfout op als de set-accessor voor een eigenschap of indexer niet toegankelijk is. Als dit het geval is, vergroot de toegankelijkheid van de accessor.
Bovendien stelt de methode BindingBase.Create de binding rechtstreeks op het object in met een Func
en retourneert het de instantie van het binding-object.
myEntry.SetBinding(Entry.TextProperty, new MultiBinding
{
Bindings = new Collection<BindingBase>
{
Binding.Create(static (Entry entry) => entry.FontFamily, source: RelativeBindingSource.Self),
Binding.Create(static (Entry entry) => entry.FontSize, source: RelativeBindingSource.Self),
Binding.Create(static (Entry entry) => entry.FontAttributes, source: RelativeBindingSource.Self),
},
Converter = new StringConcatenationConverter()
});
Deze gecompileerde bindingsmethoden bieden de volgende voordelen:
- Verbeterde prestaties van gegevensbindingen door bindingexpressies tijdens het compileren op te lossen in plaats van runtime.
- Een betere ervaring voor probleemoplossing voor ontwikkelaars omdat ongeldige bindingen worden gerapporteerd als buildfouten.
- Intellisense tijdens het bewerken.
Prestaties
Gecompileerde bindingen verbeteren de prestaties van gegevensbinding, waarbij het prestatievoordeel varieert:
- Een gecompileerde binding die gebruikmaakt van melding over eigenschapswijziging (bijvoorbeeld een
OneWay
,OneWayToSource
ofTwoWay
binding) wordt ongeveer acht keer sneller opgelost dan een klassieke binding. - Een gecompileerde binding die geen melding over eigenschapswijziging (d.w.w.w. een
OneTime
binding) gebruikt, wordt ongeveer 20 keer sneller opgelost dan een klassieke binding. - Het instellen van de BindingContext voor een gecompileerde binding die gebruikmaakt van melding over eigenschapswijziging (bijvoorbeeld een
OneWay
,OneWayToSource
ofTwoWay
binding) is ongeveer vijf keer sneller dan het instellen van de BindingContext op een klassieke binding. - Het instellen van de BindingContext voor een gecompileerde binding die geen melding over eigenschapswijziging gebruikt (dat wil bijvoorbeeld een
OneTime
binding) is ongeveer 7 keer sneller dan het instellen van de BindingContext op een klassieke binding.
Deze prestatieverschillen kunnen worden vergroot op mobiele apparaten, afhankelijk van het gebruikte platform, de versie van het gebruikte besturingssysteem en het apparaat waarop de toepassing wordt uitgevoerd.