Delen via


Gegevensbindingen maken

Als u een gebruikersinterface hebt ontworpen met tijdelijke aanduidingen voor afbeeldingen en standaardtekst, laat deze zelfstudie zien hoe u deze verbindt met echte gegevens met behulp van gegevensbindingen. Meer informatie over het opmaken van gegevens, het synchroniseren van uw gebruikersinterface en gegevens en het verbeteren van de onderhoudbaarheid van code.

In deze zelfstudie leert u hoe u uw standaard vervangt door gegevensbindingen en andere directe koppelingen maakt tussen uw gebruikersinterface en uw gegevens. U leert ook hoe u uw gegevens kunt opmaken of converteren voor weergave en hoe u uw gebruikersinterface en gegevens synchroon houdt. Wanneer u deze zelfstudie voltooit, kunt u de eenvoud en organisatie van de XAML- en C#-code verbeteren, zodat u deze eenvoudiger kunt onderhouden en uitbreiden.

U begint met een vereenvoudigde versie van het PhotoLab-voorbeeld. Deze startersversie bevat de volledige gegevenslaag plus de basispagina-indelingen van XAML en laat veel functies over om de code gemakkelijker te laten doorlopen. Deze zelfstudie bouwt niet op tot de volledige app. Bekijk daarom de definitieve versie om functies te zien, zoals aangepaste animaties en adaptieve indelingen. U vindt de definitieve versie in de hoofdmap van de opslagplaats Windows-appsample-photo-lab .

De PhotoLab-voorbeeld-app heeft twee pagina's. Op de hoofdpagina wordt een fotogalerieweergave weergegeven, samen met enkele informatie over elk afbeeldingsbestand.

Schermopname van de hoofdpagina van de PhotoLab-app met een fotogalerieweergave met metagegevens van afbeeldingen.

Op de detailpagina wordt één foto weergegeven nadat u deze hebt geselecteerd. Met een flyoutbewerkingsmenu kunt u de foto wijzigen, de naam ervan wijzigen en opslaan.

Schermopname van de detailpagina van de PhotoLab-app met één foto met bewerkingsopties.

Vereiste voorwaarden

Deel 0: De starterscode ophalen van GitHub

Voor deze zelfstudie begint u met een vereenvoudigde versie van het PhotoLab-voorbeeld.

  1. Ga naar de GitHub-pagina voor het voorbeeld: https://github.com/Microsoft/Windows-appsample-photo-lab.

  2. Vervolgens moet u het voorbeeld klonen of downloaden. Selecteer de knop klonen of downloaden. Er wordt een submenu weergegeven. Het menu Klonen of downloaden op de GitHub-pagina van het PhotoLab-voorbeeld

    Als u niet bekend bent met GitHub:

    een. Selecteer ZIP downloaden en sla het bestand lokaal op. Met deze actie wordt een .zip-bestand gedownload dat alle projectbestanden bevat die u nodig hebt.

    b. Pak het bestand uit. Gebruik Verkenner om naar het .zip bestand te bladeren dat u zojuist hebt gedownload, klik er met de rechtermuisknop op en selecteer Alles uitpakken....

    Hoofdstuk c. Blader naar uw lokale kopie van het voorbeeld en ga naar de Windows-appsample-photo-lab-master\xaml-basics-starting-points\data-binding map.

    Als u bekend bent met GitHub:

    een. Kloon de hoofdtak van de repository lokaal.

    b. Navigeer naar de map Windows-appsample-photo-lab\xaml-basics-starting-points\data-binding.

  3. Dubbelklik Photolab.sln om de oplossing te openen in Visual Studio.

Deel 1: De tijdelijke aanduidingen vervangen

In deze sectie maakt u eenmalige bindingen in gegevenssjabloon XAML om echte afbeeldingen en afbeeldingsmetagegevens weer te geven in plaats van tijdelijke aanduidingen voor inhoud.

Eenmalige bindingen zijn bedoeld voor alleen-lezen, onveranderlijke gegevens. Ze zijn eenvoudig te ontwikkelen en bieden hoogwaardige prestaties zodat u grote gegevenssets kunt weergeven in GridView en ListView bedieningspanelen.

De tijdelijke aanduidingen vervangen door eenmalige bindingen

  1. Open de xaml-basics-starting-points\data-binding map en start het PhotoLab.sln bestand in Visual Studio.

  2. Zorg ervoor dat uw Solution Platform is ingesteld op x86 of x64, niet Arm en voer vervolgens de app uit. In deze stap ziet u de status van de app met tijdelijke aanduidingen voor de gebruikersinterface voordat bindingen worden toegevoegd.

    App uitvoeren met tijdelijke aanduidingen voor afbeeldingen en tekst

  3. Open MainPage.xaml en zoek naar een DataTemplatebenoemde ImageGridView_DefaultItemTemplate. U werkt deze sjabloon bij om gegevensbindingen te gebruiken.

    voorafgaand aan:

    <DataTemplate x:Key="ImageGridView_DefaultItemTemplate">
    

    De x:Key waarde wordt gebruikt door ImageGridView om deze template te selecteren voor het weergeven van gegevensobjecten.

  4. Voeg een x:DataType waarde toe aan de sjabloon.

    Na:

    <DataTemplate x:Key="ImageGridView_DefaultItemTemplate"
                  x:DataType="local:ImageFileInfo">
    

    x:DataType geeft aan voor welk type deze sjabloon is bedoeld. In dit geval is het een sjabloon voor de ImageFileInfo klasse (waarbij local: de lokale naamruimte wordt aangegeven, zoals gedefinieerd in een XMLNS-declaratie aan de bovenkant van het bestand).

    U hebt x:DataType nodig bij het gebruik van expressies in een gegevenssjabloon x:Bind, zoals hierna wordt beschreven.

  5. Zoek in de DataTemplate naar het Image-element met de naam ItemImage en vervang de Source-waarde zoals aangegeven.

    voorafgaand aan:

    <Image x:Name="ItemImage"
           Source="/Assets/StoreLogo.png"
           Stretch="Uniform" />
    

    Na:

    <Image x:Name="ItemImage"
           Source="{x:Bind ImageSource}"
           Stretch="Uniform" />
    

    x:Name identificeert een XAML-element, zodat u er ergens anders in de XAML en in de codeachter kunt verwijzen.

    x:Bind expressies leveren een waarde aan een ui-eigenschap door de waarde op te halen uit een gegevensobjecteigenschap. In sjablonen is de aangegeven eigenschap een eigenschap van waar de x:DataType eigenschap op is ingesteld. In dit geval is de gegevensbron dus de ImageFileInfo.ImageSource eigenschap.

    Opmerking

    De x:Bind waarde laat de editor ook weten over het gegevenstype, zodat u IntelliSense kunt gebruiken in plaats van in de naam van de eigenschap in een x:Bind expressie te typen. Probeer het op de code die u zojuist hebt geplakt: plaats de cursor vlak erna x:Bind en druk op de spatiebalk om een lijst met eigenschappen weer te geven waaraan u een binding kunt maken.

  6. Vervang de waarden van de andere UI-besturingselementen op dezelfde manier. (Probeer dit met IntelliSense in plaats van kopiëren/plakken!)

    voorafgaand aan:

    <TextBlock Text="Placeholder" ... />
    <StackPanel ... >
        <TextBlock Text="PNG file" ... />
        <TextBlock Text="50 x 50" ... />
    </StackPanel>
    <muxc:RatingControl Value="3" ... />
    

    Na:

    <TextBlock Text="{x:Bind ImageTitle}" ... />
    <StackPanel ... >
        <TextBlock Text="{x:Bind ImageFileType}" ... />
        <TextBlock Text="{x:Bind ImageDimensions}" ... />
    </StackPanel>
    <muxc:RatingControl Value="{x:Bind ImageRating}" ... />
    

Voer de app uit om te zien hoe deze er tot nu toe uitziet. Geen tijdelijke aanduidingen meer. Je bent goed op weg.

App uitvoeren met echte afbeeldingen en tekst in plaats van tijdelijke aanduidingen

Opmerking

Als u verder wilt experimenteren, voegt u een nieuw TextBlock toe aan de gegevenssjabloon en gebruikt u de truc x:Bind IntelliSense om een eigenschap te vinden die moet worden weergegeven.

In deze sectie maakt u eenmalige bindingen in pagina XAML om de galerieweergave te verbinden met de afbeeldingsverzameling. Deze bindingen vervangen de bestaande procedurele code in code-behind. U maakt ook een knop Verwijderen om te zien hoe de galerieweergave verandert wanneer u afbeeldingen uit de verzameling verwijdert. Tegelijkertijd leert u hoe u gebeurtenissen koppelt aan gebeurtenis-handlers voor meer flexibiliteit dan traditionele gebeurtenis-handlers.

Alle bindingen die tot nu toe worden behandeld, bevinden zich in gegevenssjablonen en verwijzen naar eigenschappen van de klasse die door de x:DataType waarde worden aangegeven. Hoe zit het met de rest van de XAML op uw pagina?

x:Bind expressies buiten gegevenssjablonen binden altijd aan de pagina zelf. Dit betekent dat u gebruik kunt maken van alles wat u in code plaatst of declareert in XAML, inclusief aangepaste eigenschappen en eigenschappen van andere UI-elementen op de pagina (zolang ze een x:Name waarde hebben).

In het PhotoLab-voorbeeld gebruikt u een binding zoals deze om het hoofdbesturingselement GridView rechtstreeks te verbinden met de verzameling afbeeldingen, in plaats van dit in code-behind te doen. Later ziet u andere voorbeelden.

Het hoofdbesturingselement GridView verbinden met de verzameling Afbeeldingen

  1. Zoek in MainPage.xaml.cs naar de GetItemsAsync-methode en verwijder de code die ItemsSource instelt.

    voorafgaand aan:

    ImageGridView.ItemsSource = Images;
    

    Na:

    // Replaced with XAML binding:
    // ImageGridView.ItemsSource = Images;
    
  2. Zoek in MainPage.xaml de GridView met de naam ImageGridView en voeg een ItemsSource kenmerk toe. Gebruik voor de waarde een x:Bind expressie die verwijst naar de Images eigenschap die is geïmplementeerd in code-behind.

    voorafgaand aan:

    <GridView x:Name="ImageGridView"
    

    Na:

    <GridView x:Name="ImageGridView"
              ItemsSource="{x:Bind Images}"
    

    De Images eigenschap is van het type ObservableCollection<ImageFileInfo>, dus de afzonderlijke items die in de GridView eigenschap worden weergegeven, zijn van het type ImageFileInfo. Dit type komt overeen met de x:DataType waarde die wordt beschreven in deel 1.

Alle bindingen die u eerder hebt gezien, zijn eenmalige, alleen-lezen bindingen. Dit is het standaardgedrag voor gewone x:Bind expressies. De gegevens worden alleen tijdens de initialisatie geladen, wat zorgt voor hoogwaardige bindingen, perfect voor het ondersteunen van meerdere, complexe weergaven van grote gegevenssets.

Zelfs de binding die ItemsSource u zojuist hebt toegevoegd, is een eenmalige, alleen-lezen binding met een onveranderlijke eigenschapswaarde, maar er is hier een belangrijk onderscheid te maken. De onveranderlijke waarde van de Images eigenschap is één specifiek exemplaar van een verzameling, eenmaal geïnitialiseerd, zoals hier wordt weergegeven.

private ObservableCollection<ImageFileInfo> Images { get; }
    = new ObservableCollection<ImageFileInfo>();

De Images eigenschapswaarde wordt nooit gewijzigd, maar omdat de eigenschap van het type ObservableCollection<T>is, kan de inhoud van de verzameling worden gewijzigd en ziet de binding automatisch de wijzigingen en werkt de gebruikersinterface bij.

Als u dit gedrag wilt testen, voegt u tijdelijk een knop toe waarmee de geselecteerde afbeelding wordt verwijderd. Deze knop bevindt zich niet in de definitieve versie, omdat u door een afbeelding te selecteren naar een detailpagina gaat. Het gedrag van ObservableCollection<T> is echter nog steeds belangrijk in het uiteindelijke PhotoLab-voorbeeld omdat de XAML in de paginaconstructor wordt geïnitialiseerd (via de InitializeComponent methode-aanroep), maar de Images collectie later in de GetItemsAsync methode wordt ingevuld.

Knop Verwijderen toevoegen

  1. Bekijk in MainPage.xaml de CommandBar met de naam MainCommandBar en voeg een nieuwe knop toe vóór de zoomknop. (De zoombesturingselementen werken nog niet. U koppelt deze aan het volgende deel van de zelfstudie.)

    <AppBarButton Icon="Delete"
                  Label="Delete selected image"
                  Click="{x:Bind DeleteSelectedImage}" />
    

    Als u al bekend bent met XAML, kan deze Click waarde er ongebruikelijk uitzien. In eerdere versies van XAML moest u deze instellen op een methode met een specifieke handtekening voor gebeurtenis-handler, meestal inclusief parameters voor de afzender van de gebeurtenis en een gebeurtenisspecifiek argumentenobject. U kunt deze techniek nog steeds gebruiken wanneer u de gebeurtenisargumenten nodig hebt, maar u kunt ook verbinding maken met x:Bindandere methoden. Als u de gebeurtenisgegevens bijvoorbeeld niet nodig hebt, kunt u verbinding maken met methoden die geen parameters hebben, zoals hier.

  2. Voeg in MainPage.xaml.cs de DeleteSelectedImage methode toe.

    private void DeleteSelectedImage() =>
        Images.Remove(ImageGridView.SelectedItem as ImageFileInfo);
    

    Met deze methode verwijdert u gewoon de geselecteerde afbeelding uit de Images verzameling.

Voer nu de app uit en gebruik de knop om enkele afbeeldingen te verwijderen. Zoals u ziet, wordt de gebruikersinterface automatisch bijgewerkt, dankzij gegevensbinding en het ObservableCollection<T> type.

Opmerking

Met deze code wordt alleen het ImageFileInfo exemplaar uit de Images verzameling in de actieve app verwijderd. Het afbeeldingsbestand wordt niet van de computer verwijderd.

Deel 3: De zoomschuifregelaar instellen

In dit deel maakt u eenrichtingsbindingen van een besturingselement in de gegevenssjabloon naar de zoomschuifregelaar, die zich buiten de sjabloon bevindt. U leert ook dat u gegevensbinding kunt gebruiken met veel besturingseigenschappen, niet alleen de meest voor de hand liggende eigenschappen, zoals TextBlock.Text en Image.Source.

De afbeeldingsgegevenssjabloon binden aan de zoomschuifregelaar

  • Zoek de DataTemplate met de naam ImageGridView_DefaultItemTemplate en vervang de **Height** en Width waarden van de Grid controle bovenaan de sjabloon.

    Vóór

    <DataTemplate x:Key="ImageGridView_DefaultItemTemplate"
                  x:DataType="local:ImageFileInfo">
        <Grid Height="200"
              Width="200"
              Margin="{StaticResource LargeItemMargin}">
    

    Na

    <DataTemplate x:Key="ImageGridView_DefaultItemTemplate"
                  x:DataType="local:ImageFileInfo">
        <Grid Height="{Binding Value, ElementName=ZoomSlider}"
              Width="{Binding Value, ElementName=ZoomSlider}"
              Margin="{StaticResource LargeItemMargin}">
    

Hebt u gemerkt dat dit expressies zijn Binding en geen x:Bind expressies? Dit is de oude manier om gegevensbindingen uit te voeren en is meestal verouderd. x:Bind doet bijna alles wat dat Binding doet, en meer. Wanneer u echter in een gegevenssjabloon gebruikt x:Bind , wordt het gekoppeld aan het type dat in de x:DataType waarde is gedeclareerd. Hoe koppelt u iets in de sjabloon aan iets in de pagina XAML of in de code-behind? U moet een oude Binding expressie gebruiken.

Binding expressies herkennen de x:DataType waarde niet, maar deze Binding expressies hebben ElementName waarden die bijna op dezelfde manier werken. Deze geven aan de bindingsengine aan dat bindingswaarde een binding is met de Value eigenschap van het opgegeven element op de pagina (dat wil zeggen het element met die x:Name waarde). Als u een eigenschap in code-behind wilt koppelen, zou het er ongeveer als {Binding MyCodeBehindProperty, ElementName=page} uitzien, waarbij page verwijst naar de waarde x:Name die is ingesteld op het Page-element in XAML.

Opmerking

Standaard zijn Binding expressies eenmanier, wat betekent dat de gebruikersinterface automatisch wordt bijgewerkt wanneer de afhankelijke eigenschapswaarde wordt gewijzigd.

De standaardinstelling voor x:Bind is daarentegen één keer, wat betekent dat eventuele wijzigingen in de gebonden eigenschap worden genegeerd. Dit is de standaardinstelling omdat dit de meest krachtige optie is en de meeste bindingen betrekking hebben op statische, alleen-lezen gegevens.

De les hier is dat als u eigenschappen gebruikt met x:Bind die hun waarden kunnen wijzigen, u ervoor moet zorgen dat u Mode=OneWay of Mode=TwoWay toevoegt. In de volgende sectie ziet u voorbeelden hiervan.

Voer de app uit en gebruik de schuifregelaar om de afmetingen van de afbeeldingssjabloon te wijzigen. Zoals u kunt zien, is het effect vrij krachtig zonder veel code nodig te hebben.

App uitvoeren met zoomschuifregelaar met

Opmerking

Voor een uitdaging kunt u andere UI-eigenschappen koppelen aan de eigenschap zoomschuifregelaar Value of aan andere schuifregelaars die u toevoegt na de zoomschuifregelaar. U kunt bijvoorbeeld de FontSize eigenschap van de TitleTextBlock binden aan een nieuwe schuifregelaar met een standaardwaarde van 24. Zorg ervoor dat u redelijke minimum- en maximumwaarden instelt.

Deel 4: De zoomervaring verbeteren

In dit deel voegt u een aangepaste ItemSize eigenschap toe aan code-behind en maakt u eenrichtingsbindingen van de afbeeldingssjabloon naar de nieuwe eigenschap. De ItemSize waarde wordt bijgewerkt door de zoomschuifregelaar en andere factoren, zoals de wisselknop Aanpassen aan scherm en de venstergrootte, wat zorgt voor een meer verfijnde ervaring.

In tegenstelling tot ingebouwde besturingselementeigenschappen worden uw aangepaste eigenschappen niet automatisch bijgewerkt, zelfs wanneer gebruikgemaakt wordt van eenrichtings- en tweerichtingsbindingen. Ze werken prima met ééntijd bindingen, maar als u wilt dat uw eigenschapswijzigingen daadwerkelijk worden weergegeven in uw gebruikersinterface, moet u wat werk doen.

De eigenschap ItemSize maken zodat de gebruikersinterface wordt bijgewerkt

  1. Wijzig in MainPage.xaml.cs de handtekening van de MainPage klasse zodat deze de INotifyPropertyChanged interface implementeert.

    voorafgaand aan:

    public sealed partial class MainPage : Page
    

    Na:

    public sealed partial class MainPage : Page, INotifyPropertyChanged
    

    Dit informeert het bindingssysteem dat MainPage een PropertyChanged gebeurtenis heeft (die daarna wordt toegevoegd) zodat bindingen kunnen luisteren om de UI bij te werken.

  2. Voeg een PropertyChanged gebeurtenis toe aan de MainPage klasse.

    public event PropertyChangedEventHandler PropertyChanged;
    

    Deze gebeurtenis biedt de volledige implementatie die vereist is voor de INotifyPropertyChanged interface. Als u dit effect wilt hebben, moet u de gebeurtenis echter expliciet in uw aangepaste eigenschappen genereren.

  3. Voeg een eigenschap ItemSize toe en roep de gebeurtenis PropertyChanged aan in de setter.

    public double ItemSize
    {
        get => _itemSize;
        set
        {
            if (_itemSize != value)
            {
                _itemSize = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ItemSize)));
            }
        }
    }
    private double _itemSize;
    

    Met ItemSize de eigenschap wordt de waarde van een privéveld _itemSize weergegeven. Als u een back-upveld zoals dit gebruikt, kan de eigenschap controleren of een nieuwe waarde hetzelfde is als de oude waarde voordat deze een mogelijk onnodige PropertyChanged gebeurtenis genereert.

    De gebeurtenis zelf wordt gegenereerd door de methode Invoke. Het vraagteken controleert of de PropertyChanged-gebeurtenis null is, dat wil zeggen, of er al event handlers zijn toegevoegd. Elke eenrichtings- of tweerichtingsbinding voegt achter de schermen een eventhandler toe, maar als niemand luistert, gebeurt er verder niets. Als PropertyChanged echter niet null is, wordt Invoke aangeroepen met een verwijzing naar de gebeurtenisbron (de pagina zelf, vertegenwoordigd door het this sleutelwoord) en een gebeurtenis-args-object dat de naam van de eigenschap aangeeft. Met deze informatie worden alle eenrichtings- of tweerichtingsbindingen die gebonden zijn aan de eigenschap ItemSize op de hoogte gesteld van eventuele wijzigingen, waardoor ze de gebonden gebruikersinterface kunnen bijwerken.

  4. Zoek in MainPage.xaml naar de DataTemplate met de naam ImageGridView_DefaultItemTemplate en vervang de Height- en Width-waarden van de Grid-besturing aan de bovenkant van de sjabloon. (Als u de control-to-control-binding in het vorige deel van deze zelfstudie hebt uitgevoerd, zijn de enige wijzigingen het vervangen van Value door ItemSize en ZoomSlider door page. Zorg ervoor dat u dit doet voor zowel Height als Width!)

    Vóór

    <DataTemplate x:Key="ImageGridView_DefaultItemTemplate"
                  x:DataType="local:ImageFileInfo">
        <Grid Height="{Binding Value, ElementName=ZoomSlider}"
            Width="{Binding Value, ElementName=ZoomSlider}"
            Margin="{StaticResource LargeItemMargin}">
    

    Na

    <DataTemplate x:Key="ImageGridView_DefaultItemTemplate"
                  x:DataType="local:ImageFileInfo">
        <Grid Height="{Binding ItemSize, ElementName=page}"
              Width="{Binding ItemSize, ElementName=page}"
              Margin="{StaticResource LargeItemMargin}">
    

Nu de gebruikersinterface op wijzigingen kan reageren ItemSize , moet u daadwerkelijk enkele wijzigingen aanbrengen. Zoals eerder vermeld, wordt de ItemSize waarde berekend op basis van de huidige status van verschillende besturingselementen voor de gebruikersinterface, maar de berekening moet worden uitgevoerd wanneer deze besturingselementen de status wijzigen. Hiervoor gebruikt u gebeurtenisbinding, zodat bepaalde wijzigingen in de gebruikersinterface een helpermethode aanroepen die ItemSize bijwerkt.

De eigenschapswaarde ItemSize bijwerken

  1. Voeg de DetermineItemSize methode toe aan MainPage.xaml.cs.

    private void DetermineItemSize()
    {
        if (FitScreenToggle != null
            && FitScreenToggle.IsOn == true
            && ImageGridView != null
            && ZoomSlider != null)
        {
            // The 'margins' value represents the total of the margins around the
            // image in the grid item. 8 from the ItemTemplate root grid + 8 from
            // the ItemContainerStyle * (Right + Left). If those values change,
            // this value needs to be updated to match.
            int margins = (int)this.Resources["LargeItemMarginValue"] * 4;
            double gridWidth = ImageGridView.ActualWidth -
                (int)this.Resources["DefaultWindowSidePaddingValue"];
            double ItemWidth = ZoomSlider.Value + margins;
            // We need at least 1 column.
            int columns = (int)Math.Max(gridWidth / ItemWidth, 1);
    
            // Adjust the available grid width to account for margins around each item.
            double adjustedGridWidth = gridWidth - (columns * margins);
    
            ItemSize = (adjustedGridWidth / columns);
        }
        else
        {
            ItemSize = ZoomSlider.Value;
        }
    }
    
  2. Navigeer in MainPage.xaml naar de bovenkant van het bestand en voeg een SizeChanged gebeurtenisbinding toe aan het Page element.

    voorafgaand aan:

    <Page x:Name="page"
    

    Na:

    <Page x:Name="page"
          SizeChanged="{x:Bind DetermineItemSize}"
    
  3. Zoek de Slider met de naam ZoomSlider (in de sectie Page.Resources) en voeg een ValueChanged gebeurtenisbinding toe.

    voorafgaand aan:

    <Slider x:Name="ZoomSlider"
    

    Na:

    <Slider x:Name="ZoomSlider"
            ValueChanged="{x:Bind DetermineItemSize}"
    
  4. Zoek de ToggleSwitch met de naam FitScreenToggle en voeg een Toggled gebeurtenisbinding toe.

    voorafgaand aan:

    <ToggleSwitch x:Name="FitScreenToggle"
    

    Na:

    <ToggleSwitch x:Name="FitScreenToggle"
                  Toggled="{x:Bind DetermineItemSize}"
    

Voer de app uit en gebruik de zoomschuifregelaar en de wisselknop Aanpassen aan het scherm om de afmetingen van de afbeeldingssjabloon te wijzigen. Zoals u kunt zien, zorgen de meest recente wijzigingen voor een verfijndere zoom-/formaatervaring terwijl de code goed georganiseerd blijft.

App uitvoeren met fit-to-screen ingeschakeld

Opmerking

Probeer voor een uitdaging een TextBlock na de ZoomSlider eigenschap toe te voegen en de Text eigenschap aan de ItemSize eigenschap te binden. Omdat het niet in een gegevenssjabloon staat, kunt u x:Bind gebruiken in plaats van Binding, zoals bij de vorige ItemSize bindingen.

Deel 5: Gebruikersbewerkingen inschakelen

Hier maakt u tweerichtingsbindingen om gebruikers in staat te stellen waarden bij te werken, waaronder de titel van de afbeelding, classificatie en verschillende visuele effecten.

Hiervoor werkt u de bestaande DetailPageversie bij, die een viewer met één afbeelding, zoombesturingselement en bewerkingsinterface biedt.

Eerst moet u de DetailPage verbinden met de app, zodat de app naar deze locatie navigeert wanneer de gebruiker op een afbeelding in de galerieweergave klikt.

De DetailPage koppelen

  1. Zoek in MainPage.xaml de GridView met de naam ImageGridView. Als u de items klikbaar wilt maken, stelt u IsItemClickEnabled in op True en voegt u een ItemClick event-handler toe.

    Aanbeveling

    Als u de onderstaande wijziging typt in plaats van kopiëren/plakken, ziet u een Pop-upvenster van IntelliSense met de tekst '<Nieuwe gebeurtenis-handler>'. Als u op de Tab-toets drukt, wordt de waarde ingevuld met de naam van de standaardmethodehandler en wordt de methode die in de volgende stap wordt weergegeven, automatisch weergegeven. U kunt vervolgens op F12 drukken om naar de methode in de achterliggende code te navigeren.

    voorafgaand aan:

    <GridView x:Name="ImageGridView">
    

    Na:

    <GridView x:Name="ImageGridView"
              IsItemClickEnabled="True"
              ItemClick="ImageGridView_ItemClick">
    

    Opmerking

    We gebruiken hier een conventionele gebeurtenis-handler in plaats van een x:Bind-expressie. Dit komt doordat we de gebeurtenisgegevens moeten zien, zoals hierna wordt weergegeven.

  2. Voeg in MainPage.xaml.cs de gebeurtenis-handler toe (of vul deze in als u de tip in de laatste stap hebt gebruikt).

    private void ImageGridView_ItemClick(object sender, ItemClickEventArgs e)
    {
        this.Frame.Navigate(typeof(DetailPage), e.ClickedItem);
    }
    

    Met deze methode navigeert u naar de detailpagina en geeft u het geklikt item door. Dit is een ImageFileInfo object dat wordt gebruikt door DetailPage.OnNavigatedTo voor het initialiseren van de pagina. U hoeft deze methode niet in deze zelfstudie te implementeren, maar u kunt een kijkje nemen om te zien wat deze doet.

  3. (Optioneel) Verwijder of maak een opmerking bij alle bedieningselementen die u hebt toegevoegd in eerdere speelpunten die werken met de geselecteerde afbeelding. Als je ze laat staan, schaadt dat niets, maar het is nu veel moeilijker om een afbeelding te selecteren zonder naar de detailpagina te navigeren.

Nu u de twee pagina's hebt verbonden, voert u de app uit en kijkt u rond. Alles werkt behalve de besturingselementen in het bewerkingsvenster, die niet reageren wanneer u de waarden probeert te wijzigen.

Zoals u ziet, wordt in het titeltekstvak de titel weergegeven en kunt u wijzigingen typen. U moet de focus wijzigen in een ander besturingselement om de wijzigingen door te voeren, maar de titel in de linkerbovenhoek van het scherm wordt nog niet bijgewerkt.

Alle besturingselementen zijn al gebonden aan de eenvoudige x:Bind-expressies die we in deel 1 hebben behandeld. Als u weet, betekent dit dat ze allemaal eenmalige bindingen zijn, wat verklaart waarom wijzigingen in de waarden niet zijn geregistreerd. Om dit op te lossen, hoeven we ze alleen maar om te zetten in tweerichtingsbindingen.

De besturingselementen voor bewerken interactief maken

  1. Zoek in DetailPage.xaml de TextBlock met de naam TitleTextBlock en het besturingselement RatingControl erna en werk de bijbehorende x:Bind expressies bij om Mode=TwoWayop te nemen.

    voorafgaand aan:

    <TextBlock x:Name="TitleTextBlock"
               Text="{x:Bind item.ImageTitle}"
               ... >
    <muxc:RatingControl Value="{x:Bind item.ImageRating}"
                            ... >
    

    Na:

    <TextBlock x:Name="TitleTextBlock"
               Text="{x:Bind item.ImageTitle, Mode=TwoWay}"
               ... >
    <muxc:RatingControl Value="{x:Bind item.ImageRating, Mode=TwoWay}"
                            ... >
    
  2. Doe hetzelfde voor alle effectschuifregelaars die na het classificatiebesturingselement komen.

    <Slider Header="Exposure"    ... Value="{x:Bind item.Exposure, Mode=TwoWay}" ...
    <Slider Header="Temperature" ... Value="{x:Bind item.Temperature, Mode=TwoWay}" ...
    <Slider Header="Tint"        ... Value="{x:Bind item.Tint, Mode=TwoWay}" ...
    <Slider Header="Contrast"    ... Value="{x:Bind item.Contrast, Mode=TwoWay}" ...
    <Slider Header="Saturation"  ... Value="{x:Bind item.Saturation, Mode=TwoWay}" ...
    <Slider Header="Blur"        ... Value="{x:Bind item.Blur, Mode=TwoWay}" ...
    

De tweerichtingsmodus, zoals u zou verwachten, betekent dat de gegevens in beide richtingen worden verplaatst wanneer er wijzigingen aan beide zijden zijn.

Net als bij de eenrichtingsbindingen die eerder zijn besproken, worden deze tweerichtingsbindingen nu bijgewerkt wanneer de gebonden eigenschappen veranderen, dankzij de INotifyPropertyChanged-implementatie in de ImageFileInfo-klasse. Met binding in twee richtingen worden de waarden echter ook verplaatst van de gebruikersinterface naar de afhankelijke eigenschappen wanneer de gebruiker met het besturingselement communiceert. Er is niets meer nodig aan de XAML-zijde.

Open de app en probeer de bewerkingselementen. Zoals u ziet, is dit van invloed op de afbeeldingswaarden wanneer u een wijziging aanbrengt en blijven deze wijzigingen behouden wanneer u teruggaat naar de hoofdpagina.

Deel 6: Waarden opmaken via functiebinding

Nog een laatste probleem. Als u de effectschuifregelaars verplaatst, veranderen de labels ernaast nog steeds niet.

effectschuifregelaars met standaardlabelwaarden

Het laatste deel in deze zelfstudie is het toevoegen van bindingen waarmee de schuifregelaarwaarden voor weergave worden opgemaakt.

Bind de labels van de effectschuifregelaar en maak de waarden op voor weergave.

  1. Zoek de TextBlock na de Exposure schuifregelaar en vervang de Text waarde door de bindingexpressie die hier wordt weergegeven.

    voorafgaand aan:

    <Slider Header="Exposure" ... />
    <TextBlock ... Text="0.00" />
    

    Na:

    <Slider Header="Exposure" ... />
    <TextBlock ... Text="{x:Bind item.Exposure.ToString('N', culture), Mode=OneWay}" />
    

    Dit wordt een functiebinding genoemd omdat u een binding hebt met de retourwaarde van een methode. De methode moet toegankelijk zijn via de code-behind van de pagina of het x:DataType-type wanneer u zich in een gegevenssjabloon bevindt. In dit geval is de methode de bekende .NET-methode ToString , die wordt geopend via de itemeigenschap van de pagina en vervolgens via de Exposure eigenschap van het item. (Dit laat zien hoe u verbinding kunt maken met methoden en eigenschappen die diep zijn genest in een keten van verbindingen.)

    Functiebinding is een ideale manier om waarden op te maken voor weergave, omdat u andere bindingsbronnen als methodeargumenten kunt doorgeven. De bindingsexpressie luistert naar wijzigingen in deze waarden zoals verwacht met de eenrichtingsmodus. In dit voorbeeld is het argument cultuur een verwijzing naar een constant veld dat is geïmplementeerd in de code-behind, maar het kan net zo eenvoudig een eigenschap zijn die PropertyChanged gebeurtenissen oproept. In dat geval zouden wijzigingen in de eigenschapswaarde ertoe leiden dat de x:Bind-uitdrukking ToString aanroept met de nieuwe waarde en daarna het resultaat in de gebruikersinterface bijwerkt.

  2. Doe hetzelfde voor de TextBlock's die de andere effectschuifregelaars labelen.

    <Slider Header="Temperature" ... />
    <TextBlock ... Text="{x:Bind item.Temperature.ToString('N', culture), Mode=OneWay}" />
    
    <Slider Header="Tint" ... />
    <TextBlock ... Text="{x:Bind item.Tint.ToString('N', culture), Mode=OneWay}" />
    
    <Slider Header="Contrast" ... />
    <TextBlock ... Text="{x:Bind item.Contrast.ToString('N', culture), Mode=OneWay}" />
    
    <Slider Header="Saturation" ... />
    <TextBlock ... Text="{x:Bind item.Saturation.ToString('N', culture), Mode=OneWay}" />
    
    <Slider Header="Blur" ... />
    <TextBlock ... Text="{x:Bind item.Blur.ToString('N', culture), Mode=OneWay}" />
    

Wanneer u nu de app uitvoert, werkt alles, inclusief de labels van de schuifregelaar.

schuifregelaars voor effect met werkende labels

Verschillen tussen binding en x:Bind

Wanneer u gegevensbindingen maakt in XAML in uw UWP-apps, kunt u kiezen tussen Binding en x:Bind. Dit zijn de belangrijkste verschillen:

  • x:Bind: Biedt compileertijdvalidatie, betere prestaties en is sterk getypt. Het is het meest geschikt voor scenario's waarbij de gegevensstructuur bekend is tijdens het compileren.
  • Binding: biedt runtime-evaluatie en meer flexibiliteit voor dynamische scenario's, zoals wanneer de gegevensstructuur tijdens runtime wordt bepaald.

Scenario's die niet worden ondersteund door x:Bind

Hoewel x:Bind het zeer efficiënt is, heeft het beperkingen in bepaalde scenario's:

  • Dynamische gegevensstructuren: x:Bind kan niet worden gebruikt wanneer de gegevensstructuur tijdens runtime wordt bepaald.
  • Element-naar-element-binding: Directe binding tussen twee UI-elementen wordt niet ondersteund door x:Bind.
  • Overname van DataContext: In tegenstelling tot Binding, x:Bind erft de DataContext van een bovenliggend element niet automatisch.
  • Bindingen in twee richtingen: x:Bind ondersteunt bindingen in twee richtingen, waardoor wijzigingen vanuit de gebruikersinterface weer naar de broneigenschap kunnen stromen. Om de gebruikersinterface bij te werken wanneer de broneigenschap verandert (zowel bij eenrichtings- als tweerichtingsbindingen), moet u INotifyPropertyChanged implementeren op uw gegevensobjecten.

Raadpleeg de volgende bronnen voor meer informatie en voorbeelden:

Conclusie

In deze zelfstudie hebt u een idee van gegevensbinding gekregen en hebt u enkele van de beschikbare functionaliteit getoond. Eén woord van voorzichtigheid voordat we inpakken: niet alles is bindbaar en soms zijn de waarden waarmee u verbinding probeert te maken niet compatibel met de eigenschappen die u probeert te binden. Er is veel flexibiliteit in binding, maar het werkt niet in elke situatie.

Een voorbeeld van een probleem dat niet door binding wordt opgelost, is wanneer een bedieningselement geen geschikte eigenschappen heeft om aan te binden, zoals bij de zoomfunctie van een detailpagina. Deze zoomschuifregelaar moet communiceren met de ScrollViewer dat de afbeelding toont, maar ScrollViewer kan alleen worden aangepast via de ChangeView methode. In dit geval gebruiken we conventionele eventhandlers om de ScrollViewer en de zoomschuifregelaar gesynchroniseerd te houden; zie de ZoomSlider_ValueChanged en MainImageScroll_ViewChanged methoden in DetailPage voor meer informatie.

Binding is echter een krachtige en flexibele manier om uw code te vereenvoudigen en uw UI-logica gescheiden te houden van uw gegevenslogica. Dit maakt het voor u veel gemakkelijker om beide zijden van deze splitsing aan te passen, terwijl het risico op het introduceren van bugs aan de andere kant wordt verminderd.

Een voorbeeld van de gebruikersinterface en gegevensscheiding is met de ImageFileInfo.ImageTitle eigenschap. Deze eigenschap (en de ImageRating eigenschap) is iets anders dan de ItemSize eigenschap die u in deel 4 hebt gemaakt, omdat de waarde wordt opgeslagen in de metagegevens van het bestand (beschikbaar gemaakt via het ImageProperties type) in plaats van in een veld. Retourneert bovendien ImageTitle de ImageName waarde (ingesteld op de bestandsnaam) als er geen titel in de metagegevens van het bestand staat.

public string ImageTitle
{
    get => String.IsNullOrEmpty(ImageProperties.Title) ? ImageName : ImageProperties.Title;
    set
    {
        if (ImageProperties.Title != value)
        {
            ImageProperties.Title = value;
            var ignoreResult = ImageProperties.SavePropertiesAsync();
            OnPropertyChanged();
        }
    }
}

Zoals u kunt zien, werkt de setter de ImageProperties.Title eigenschap bij en roept SavePropertiesAsync deze vervolgens aan om de nieuwe waarde naar het bestand te schrijven. (Dit is een asynchrone methode, maar we kunnen het await trefwoord in een eigenschap niet gebruiken en u wilt dit niet omdat eigenschaps getters en setters onmiddellijk moeten worden voltooid. In plaats daarvan roept u de methode aan en negeert u het Task object dat het retourneert.)

Verdergaan

Nu u dit lab hebt voltooid, hebt u voldoende bindingskennis om een probleem zelf aan te pakken.

Zoals u misschien hebt opgemerkt, wordt, als u het zoomniveau op de detailpagina wijzigt, automatisch opnieuw ingesteld wanneer u achteruit navigeert en dezelfde afbeelding opnieuw selecteert. Kunt u bepalen hoe u het zoomniveau voor elke afbeelding afzonderlijk kunt behouden en herstellen? Succes!

U hebt alle informatie die u nodig hebt in deze zelfstudie, maar als u meer hulp nodig hebt, zijn de documenten voor gegevensbinding slechts een klik verwijderd. Begin hier: