XAML-översikt (WPF .NET)
Den här artikeln beskriver funktionerna i XAML-språket och visar hur du kan använda XAML för att skriva WPF-appar (Windows Presentation Foundation). I den här artikeln beskrivs specifikt XAML som implementerat av WPF. XAML i sig är ett större språkkoncept än WPF.
XAML är ett deklarativt påläggsspråk. Enligt .NET-programmeringsmodellen förenklar XAML skapandet av ett användargränssnitt för en .NET-app. Du kan skapa synliga gränssnittselement i det deklarativa XAML-uppmärkningsspråket och sedan separera användargränssnittsdefinitionen från körningslogiken med hjälp av code-behind-filer som är anslutna till markeringen via delvisa klassdefinitioner. XAML representerar direkt instansiering av objekt i en specifik uppsättning underliggande typer som definierats i assembly. Detta är till skillnad från de flesta andra markeringsspråk, som vanligtvis är tolkade språk utan en sådan direkt koppling till ett bakomliggande typsystem. XAML möjliggör ett arbetsflöde där separata parter kan arbeta med användargränssnittet och logiken i en app med hjälp av potentiellt olika verktyg.
När de representeras som text är XAML-filer XML-filer som vanligtvis har .xaml
-tillägget. Filerna kan kodas av valfri XML-kodning, men kodning som UTF-8 är typisk.
I följande exempel visas hur du kan skapa en knapp som en del av ett användargränssnitt. Det här exemplet är avsett att ge dig en smak av hur XAML representerar vanliga UI-programmeringsmetaforer (det är inte ett fullständigt exempel).
<StackPanel>
<Button Content="Click Me"/>
</StackPanel>
I följande avsnitt förklaras de grundläggande formerna av XAML-syntax och ett kort markeringsexempel. De här avsnitten är inte avsedda att ge fullständig information om varje syntaxformulär, till exempel hur dessa representeras i backningstypsystemet. Mer information om detaljerna i XAML-syntax finns i XAML-syntax i detalj.
Mycket av materialet i de kommande avsnitten kommer att vara elementärt för dig om du tidigare har bekantat dig med XML-språket. Detta är en följd av en av de grundläggande designprinciperna för XAML. XAML-språket definierar egna begrepp, men dessa begrepp fungerar inom XML-språket och markeringsformuläret.
Ett objektelement deklarerar vanligtvis en instans av en typ. Den typen definieras i de sammansättningar som refereras av den teknik som använder XAML som språk.
Objektelementsyntaxen börjar alltid med en inledande vinkelparentes (<
). Detta följs av namnet på den typ där du vill skapa en instans. (Namnet kan innehålla ett prefix, ett begrepp som kommer att förklaras senare.) Därefter kan du även deklarera attribut för objektelementet. Slutför objektelementtaggen genom att avsluta med en avslutande vinkelparentes (>
). Du kan i stället använda ett självslutande formulär som inte har något innehåll genom att fylla i taggen med ett snedstreck och avslutande vinkelparentes i följd (/>
). Titta till exempel på det tidigare visade kodfragmentet igen.
<StackPanel>
<Button Content="Click Me"/>
</StackPanel>
Detta anger två objektelement: <StackPanel>
(med innehåll och en avslutande tagg senare) och <Button .../>
(det självslutande formuläret med flera attribut). Objektelementen StackPanel
och Button
var och en mappas till namnet på en klass som definieras av WPF och ingår i WPF-samlingarna. När du anger en objektelementtagg skapar du en instruktion för XAML-bearbetning för att skapa en ny instans av den underliggande typen. Varje instans skapas genom att anropa den parameterlösa konstruktorn av den underliggande typen vid parsning och inläsning av XAML.
Egenskaper för ett objekt kan ofta uttryckas som attribut för objektelementet. Attributsyntaxen namnger den objektegenskap som anges, följt av tilldelningsoperatorn (=). Värdet för ett attribut anges alltid som en sträng som finns inom citattecken.
Attributsyntax är den mest strömlinjeformade egenskapsinställningssyntaxen och är den mest intuitiva syntaxen att använda för utvecklare som tidigare har använt markeringsspråk. Följande markering skapar till exempel en knapp med röd text och en blå bakgrund med en visningstext på Content
.
<Button Background="Blue" Foreground="Red" Content="This is a button"/>
För vissa egenskaper för ett objektelement är attributsyntax inte möjligt, eftersom det objekt eller den information som krävs för att ange egenskapsvärdet inte kan uttryckas tillräckligt inom citattecknet och strängbegränsningarna för attributsyntaxen. I dessa fall kan en annan syntax som kallas egenskapselementsyntax användas.
Syntaxen för starttaggen för egenskapselementet är <TypeName.PropertyName>
. I allmänhet är innehållet i taggen ett objektelement av den typ som egenskapen tar som värde. När du har angett innehållet måste du stänga egenskapselementet med en sluttagg. Syntaxen för sluttaggen är </TypeName.PropertyName>
.
Om en attributsyntax är möjlig är det vanligtvis enklare att använda attributsyntaxen och aktivera en mer kompakt markering, men det är ofta bara en fråga om stil, inte en teknisk begränsning. I följande exempel visas samma egenskaper som i föregående attributsyntaxexempel, men den här gången med hjälp av egenskapselementsyntax för alla egenskaper för Button
.
<Button>
<Button.Background>
<SolidColorBrush Color="Blue"/>
</Button.Background>
<Button.Foreground>
<SolidColorBrush Color="Red"/>
</Button.Foreground>
<Button.Content>
This is a button
</Button.Content>
</Button>
XAML-språket innehåller vissa optimeringar som ger lättläst markering. En sådan optimering är att om en viss egenskap tar en samlingstyp blir objekt som du deklarerar som underordnade element i egenskapens värde en del av samlingen. I det här fallet är en samling underordnade objektelement värdet som anges till samlingsegenskapen.
I följande exempel visas samlingssyntax för att ange värden för egenskapen GradientStops.
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<!-- no explicit new GradientStopCollection, parser knows how to find or create -->
<GradientStop Offset="0.0" Color="Red" />
<GradientStop Offset="1.0" Color="Blue" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
XAML anger en språkfunktion där en klass kan ange exakt en av dess egenskaper som XAML-innehåll egenskap. Underordnade element i objektelementet används för att ställa in värdet på innehållsegenskapen. För egenskapen innehåll kan du alltså unikt utelämna ett egenskapselement när du anger den egenskapen i XAML-markeringen och skapa en mer synlig överordnad/underordnad metafor i markeringen.
Till exempel anger Border en innehållsegenskap för Child. Följande två Border-element behandlas identiskt. Den första utnyttjar syntaxen för innehållsegenskapen och utelämnar egenskapselementet Border.Child
. Den andra visar Border.Child
explicit.
<Border>
<TextBox Width="300"/>
</Border>
<!--explicit equivalent-->
<Border>
<Border.Child>
<TextBox Width="300"/>
</Border.Child>
</Border>
Som en regel för XAML-språket måste värdet för en XAML-innehållsegenskap anges antingen helt före eller helt efter andra egenskapselement i objektelementet. Följande kodexempel kompileras inte, till exempel.
<Button>I am a
<Button.Background>Blue</Button.Background>
blue button</Button>
Mer information om detaljerna i XAML-syntax finns i XAML-syntax i detalj.
Ett litet antal XAML-element kan bearbeta text direkt som innehåll. För att aktivera detta måste ett av följande fall vara sant:
Klassen måste deklarera en innehållsegenskap och den innehållsegenskapen måste vara av en typ som kan tilldelas en sträng (typen kan vara Object). Till exempel använder vilket som helst ContentControlContent som innehållsegenskap och typ Object, och detta stöder följande användning på en ContentControl, till exempel en Button:
<Button>Hello</Button>
.Typen måste deklarera en typkonverterare, i vilket fall textinnehållet används som initieringstext för den typkonverteraren. Till exempel konverterar
<Brush>Blue</Brush>
innehållsvärdet förBlue
till en pensel. Det här fallet är mindre vanligt i praktiken.Typen måste vara ett känt XAML-språksprimitiv.
Tänk på det här exemplet.
<StackPanel>
<Button>First Button</Button>
<Button>Second Button</Button>
</StackPanel>
Här är varje Button ett underordnat element i StackPanel. Det här är en effektiv och intuitiv markering som utelämnar två taggar av två olika skäl.
utelämnade egenskapselementet StackPanel.Children:StackPanel härleds från Panel. Panel definierar Panel.Children som dess XAML-innehållsegenskap.
Utelämnat UIElementCollection-objektelement: egenskapen Panel.Children tar typen UIElementCollection, som implementerar IList. Samlingens elementtagg kan utelämnas baserat på XAML-reglerna för bearbetning av samlingar, till exempel IList. (I det här fallet kan UIElementCollection faktiskt inte instansieras eftersom den inte exponerar en parameterlös konstruktor, och därför visas UIElementCollection objektelementet kommenterat ut).
<StackPanel>
<StackPanel.Children>
<!--<UIElementCollection>-->
<Button>First Button</Button>
<Button>Second Button</Button>
<!--</UIElementCollection>-->
</StackPanel.Children>
</StackPanel>
Attributsyntax kan också användas för medlemmar som är händelser i stället för egenskaper. I det här fallet är attributets namn namnet på händelsen. I WPF-implementeringen av händelser för XAML är attributets värde namnet på en hanterare som implementerar händelsens ombud. Följande markering tilldelar till exempel en hanterare för händelsen Click till en Button som skapats i markeringen.
<Button Click="Button_Click" >Click Me!</Button>
Det finns mer i händelser och XAML i WPF än bara det här exemplet på attributsyntaxen. Du kanske till exempel undrar vad ClickHandler
som refereras här representerar och hur den definieras. Detta förklaras i det kommande avsnittet Events och XAML code-behind i den här artikeln.
I allmänhet är XAML skiftlägeskänsligt. För att lösa säkerhetskopieringstyper är WPF XAML skiftlägeskänsligt av samma regler som CLR är skiftlägeskänsligt. Objektelement, egenskapselement och attributnamn måste alla anges med hjälp av det känsliga höljet jämfört med namnet på den underliggande typen i sammansättningen eller med en medlem av en typ. XAML-språknyckelord och primitiver är också skiftlägeskänsliga. Värden är inte alltid skiftlägeskänsliga. Skiftlägeskänslighet för värden beror på beteendet hos typkonverteraren som är kopplad till den egenskap som tar emot värdet eller typen av egenskapsvärdet. Egenskaper som tar Boolean typ kan till exempel ta antingen true
eller True
som motsvarande värden, men bara på grund av att den interna WPF XAML-parsertypkonverteringen för sträng till Boolean redan tillåter dessa som motsvarigheter.
WPF XAML-processorer och serialiserare ignorerar eller tar bort alla icke-signifikanta mellanrum och normaliserar alla signifikanta mellanrum. Detta överensstämmer med standardrekommendationerna för white space-beteende i XAML-specifikationen. Det här beteendet får bara konsekvenser när du anger strängar i XAML-innehållsegenskaper. I enklaste termer konverterar XAML blanksteg, radmatningstecken och tabbtecken till blanksteg och bevarar sedan ett blanksteg om det hittas i endera änden av en sammanhängande sträng. Den fullständiga förklaringen av XAML-hantering av tomt utrymme beskrivs inte i den här artikeln. Mer information finns i Bearbetning av tomt utrymme i XAML-.
Markeringstillägg är ett XAML-språkkoncept. När det används för att ange värdet för en attributsyntax anger klammerparenteser ({
och }
) användning av markeringstillägg. Den här användningen instruerar XAML-bearbetningen att avvika från den allmänna behandlingen av attributvärden som antingen en bokstavlig sträng eller ett strängkonvertibelt värde.
De vanligaste markeringstilläggen som används i WPF-appprogrammering är Binding
, används för databindningsuttryck och resursreferenserna StaticResource
och DynamicResource
. Genom att använda markeringstillägg kan du använda attributsyntax för att ange värden för egenskaper även om den egenskapen inte stöder en attributsyntax i allmänhet. Markeringstillägg använder ofta mellanliggande uttryckstyper för att aktivera funktioner som att skjuta upp värden eller referera till andra objekt som endast finns vid körning.
Följande markering anger till exempel värdet för egenskapen Style med hjälp av attributsyntax. Egenskapen Style tar en instans av klassen Style, som som standard inte kunde instansieras av en attributsyntaxsträng. Men i det här fallet refererar attributet till ett visst markeringstillägg, StaticResource
. När markeringstillägget bearbetas returneras en referens till ett format som tidigare instansierades som en nyckelresurs i en resursordlista.
<Window x:Class="index.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="100" Width="300">
<Window.Resources>
<SolidColorBrush x:Key="MyBrush" Color="Gold"/>
<Style TargetType="Border" x:Key="PageBackground">
<Setter Property="BorderBrush" Value="Blue"/>
<Setter Property="BorderThickness" Value="5" />
</Style>
</Window.Resources>
<Border Style="{StaticResource PageBackground}">
<StackPanel>
<TextBlock Text="Hello" />
</StackPanel>
</Border>
</Window>
En referenslista över alla tillägg för XAML som implementerats specifikt i WPF finns i WPF XAML-tillägg. En referenslista över markup extensioner som definieras av System.Xaml och är mer allmänt tillgängliga för .NET XAML-implementeringar finns i XAML-namnrymd (x:) språkfunktioner. Mer information om begrepp för markeringstillägg finns i Markup Extensions och WPF XAML.
I avsnittet XAML-syntax i kort angavs att attributvärdet måste kunna anges med en sträng. Den grundläggande, interna hanteringen av hur strängar konverteras till andra objekttyper eller primitiva värden baseras på själva String typen, tillsammans med intern bearbetning för vissa typer som DateTime eller Uri. Men många WPF-typer eller medlemmar av dessa typer utökar det grundläggande beteendet för bearbetning av strängattribut på ett sådant sätt att instanser av mer komplexa objekttyper kan anges som strängar och attribut.
Den Thickness strukturen är ett exempel på en typ som har en typkonvertering aktiverad för XAML-användning. Thickness anger mått i en kapslad rektangel och används som värde för egenskaper som Margin. Genom att placera en typkonverterare på Thicknessär alla egenskaper som använder en Thickness enklare att ange i XAML eftersom de kan anges som attribut. I följande exempel används en typkonverterings- och attributsyntax för att ange ett värde för en Margin:
<Button Margin="10,20,10,30" Content="Click me"/>
Exemplet med föregående attributsyntax motsvarar följande mer utförliga syntaxexempel, där Margin i stället anges via egenskapselementsyntax som innehåller ett Thickness objektelement. De fyra nyckelegenskaperna för Thickness anges som attribut för den nya instansen:
<Button Content="Click me">
<Button.Margin>
<Thickness Left="10" Top="20" Right="10" Bottom="30"/>
</Button.Margin>
</Button>
Anteckning
Det finns också ett begränsat antal objekt där typkonverteringen är det enda offentliga sättet att ange en egenskap till den typen utan att inkludera en underklass, eftersom själva typen inte har någon parameterlös konstruktor. Ett exempel är Cursor.
Mer information om typkonvertering finns i TypeConverters och XAML.
En XAML-fil får bara ha ett rotelement, för att vara både en välformulerad XML-fil och en giltig XAML-fil. För vanliga WPF-scenarier använder du ett rotelement som har en framträdande betydelse i WPF-appmodellen (till exempel Window eller Page för en sida, ResourceDictionary för en extern ordlista eller Application för appdefinitionen). I följande exempel visas rotelementet i en typisk XAML-fil för en WPF-sida, med rotelementet i Page.
<Page x:Class="index.Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Page1">
</Page>
Rotelementet innehåller även attributen xmlns
och xmlns:x
. Dessa attribut anger för en XAML-processor vilka XAML-namnområden som innehåller de typdefinitioner för bakgrundstyper som markeringen refererar till som element. Attributet xmlns
anger specifikt XAML-standardnamnområdet. I XAML-standardnamnområdet kan objektelement i markering anges utan ett prefix. För de flesta WPF-appscenarier, och för nästan alla exempel som anges i WPF-avsnitten i SDK, mappas standard XAML-namnområdet till WPF-namnområdet http://schemas.microsoft.com/winfx/2006/xaml/presentation
. Attributet xmlns:x
anger ytterligare ett XAML-namnområde som mappar XAML-språknamnområdet http://schemas.microsoft.com/winfx/2006/xaml
.
Den här användningen av xmlns
för att definiera ett omfång för användning och mappning av ett namnskop överensstämmer med XML 1.0-specifikationen. XAML-namnskop skiljer sig endast från XML-namnskop eftersom ett XAML-namnskop också antyder något om hur namnskopets element backas upp av typer när det gäller typupplösning och parsning av XAML.
De xmlns
attributen är endast absolut nödvändiga för rotelementet i varje XAML-fil.
xmlns
definitioner gäller för alla underordnade element i rotelementet (det här beteendet överensstämmer återigen med XML 1.0-specifikationen för xmlns
.) xmlns
attribut tillåts också för andra element under roten och tillämpas på underordnade element i det definierande elementet. Frekvent definition eller omdefiniering av XAML-namnområden kan dock resultera i ett XAML-markeringsformat som är svårt att läsa.
WPF-implementeringen av XAML-processorn innehåller en infrastruktur som är medveten om WPF-kärnsammansättningarna. WPF-kärnsammansättningarna är kända för att innehålla de typer som stöder WPF-mappningarna till XAML-standardnamnområdet. Detta aktiveras via konfiguration som är en del av din projektversionsfil och WPF-bygg- och projektsystemen. Att deklarera XAML-standardnamnområdet som standard xmlns
är därför allt som krävs för att referera till XAML-element som kommer från WPF-sammansättningar.
I det tidigare rotelementexemplet användes prefixet x:
för att mappa XAML-namnområdet http://schemas.microsoft.com/winfx/2006/xaml
, som är det dedikerade XAML-namnområdet som stöder XAML-språkkonstruktioner. Det här x:
prefixet används för att mappa det här XAML-namnområdet i mallarna för projekt, i exempel och i dokumentationen i hela denna SDK. XAML-namnområdet för XAML-språket innehåller flera programmeringskonstruktioner som du använder ofta i XAML. Följande är en lista över de vanligaste x:
prefixprogrammeringskonstruktioner som du kommer att använda:
x:Key: Anger en unik nyckel för varje resurs i en ResourceDictionary (eller liknande ordlistebegrepp i andra ramverk).
x:Key
står förmodligen för 90 procent av dex:
användningar som visas i en typisk WPF-app.x:Class: Anger CLR-namnområdet och klassnamnet för klassen som tillhandahåller kod bakom för en XAML-sida. Du måste ha en sådan klass för att stödja code-behind som följer WPF-programmeringsmodellen, och därför ser du ofta
x:
mappad, även om resurser inte finns.x:Name: Anger ett körningsobjektnamn för den instans som finns i körningskoden när ett objektelement har bearbetats. I allmänhet använder du ofta en WPF-definierad motsvarande egenskap för x:Name. Sådana egenskaper mappas specifikt till en CLR-stödegenskap och är därför mer praktiska för apputveckling, där du ofta använder körkod för att hitta de namngivna elementen från initierad XAML-kod. Den vanligaste sådan egenskapen är FrameworkElement.Name. Du kan fortfarande använda x:Name när motsvarande WPF-ramverksnivå Name egenskap inte stöds i en viss typ. Detta inträffar i vissa animeringsscenarier.
x:Static: Aktiverar en referens som returnerar ett statiskt värde som annars inte är en XAML-kompatibel egenskap.
x:Type: Skapar en Type referens baserat på ett typnamn. Detta används för att ange attribut som tar Type, till exempel Style.TargetType, även om egenskapen ofta har inbyggd sträng-till-Type konvertering på ett sådant sätt att x:Type markeringstilläggsanvändning är valfri.
Det finns ytterligare programmeringskonstruktioner i namnområdet x:
prefix/XAML, som inte är lika vanliga. För mer information, se språkfunktionerna för XAML-namnområde (x:) .
För dina egna anpassade sammansättningar eller för sammansättningar utanför WPF-kärnan i PresentationCore, PresentationFramework och WindowsBasekan du ange sammansättningen som en del av en anpassad xmlns
mappning. Du kan sedan referera till typer från den sammansättningen i din XAML, så länge den typen är korrekt implementerad för att stödja de XAML-användningar som du försöker använda.
Följande är ett grundläggande exempel på hur anpassade prefix fungerar i XAML-markering. Prefixet custom
definieras i rotelementtaggen och mappas till en specifik sammansättning som är paketerad och tillgänglig med appen. Den här samlingen innehåller en typ NumericUpDown
, som implementeras för att stödja allmän XAML-användning samt med en klassärvning som tillåter infogning vid denna specifika punkt i en WPF XAML-innehållsmodell. En instans av den här NumericUpDown
-kontrollen deklareras som ett objektelement med hjälp av prefixet så att en XAML-parser vet vilket XAML-namnområde som innehåller typen och därför var bakgrundssammansättningen är som innehåller typdefinitionen.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:custom="clr-namespace:NumericUpDownCustomControl;assembly=CustomLibrary"
>
<StackPanel Name="LayoutRoot">
<custom:NumericUpDown Name="numericCtrl1" Width="100" Height="60"/>
...
</StackPanel>
</Page>
Mer information om anpassade typer i XAML finns i XAML och anpassade klasser för WPF.
Mer information om hur XML-namnområden och kodnamnområden i sammansättningar är relaterade finns i XAML-namnområden och namnområdesmappning för WPF XAML.
De flesta WPF-appar består av både XAML-markering och bakomliggande kod. I ett projekt skrivs XAML som en .xaml
fil, och ett CLR-språk som Microsoft Visual Basic eller C# används för att skriva en kod bakom fil. När en XAML-fil kompileras som en del av WPF-programmerings- och programmodellerna identifieras platsen för XAML-kod bakom filen för en XAML-fil genom att ange ett namnområde och en klass som x:Class
attribut för rotelementet i XAML.
I exemplen hittills har du sett flera knappar, men ingen av dessa knappar har något logiskt beteende associerat med dem ännu. Den primära mekanismen på programnivå för att lägga till ett beteende för ett objektelement är att använda en befintlig händelse i elementklassen och att skriva en specifik hanterare för den händelsen som anropas när händelsen aktiveras vid körning. Händelsenamnet och namnet på hanteraren som ska användas anges i markering, medan koden som implementerar hanteraren definieras i koden bakom.
<Page x:Class="ExampleNamespace.ExamplePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<Button Click="Button_Click">Click me</Button>
</StackPanel>
</Page>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace ExampleNamespace;
public partial class ExamplePage : Page
{
public ExamplePage() =>
InitializeComponent();
private void Button_Click(object sender, RoutedEventArgs e)
{
var buttonControl = (Button)e.Source;
buttonControl.Foreground = Brushes.Red;
}
}
Class ExamplePage
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
Dim buttonControl = DirectCast(e.Source, Button)
buttonControl.Foreground = Brushes.Red
End Sub
End Class
Observera att filen bakom koden använder CLR-namnområdet ExampleNamespace
(namnområdet visas inte i Visual Basic) och deklarerar ExamplePage
som en partiell klass inom namnområdet. Detta motsvarar x:Class
attributvärdet för ExampleNamespace
.
ExamplePage
som angavs i markupsroten. WPF-markeringskompilatorn skapar en partiell klass för alla kompilerade XAML-filer genom att härleda en klass från rotelementtypen. När du anger kod bakom som också definierar samma partiella klass kombineras den resulterande koden inom samma namnområde och klass för den kompilerade appen.
Viktigt
I Visual Basic är rotnamnområdet underförstått för både XAML och code-behind. Endast kapslade namnområden visas. Den här artikeln visar C#-projektets XAML.
Mer information om kraven för "code-behind"-programmering i WPF finns i "Code-behind", "Event Handler" och "Partial Class Requirements" i WPF.
Om du inte vill skapa en separat kod bakom fil kan du även infoga koden i en XAML-fil. Infogad kod är dock en mindre mångsidig teknik som har betydande begränsningar. Mer information finns i Code-Behind och XAML i WPF.
En viss händelsefunktion som är grundläggande för WPF är en dirigerad händelse. Routade händelser gör det möjligt för ett element att hantera en händelse som har genererats av ett annat element, så länge elementen är anslutna via en trädrelation. När du anger händelsehantering med ett XAML-attribut kan den dirigerade händelsen lyssnas efter och hanteras på alla element, inklusive element som inte listar den specifika händelsen i tabellen klassmedlemmar. Detta uppnås genom att kvalificera attributet för händelsenamnet med det ägande klassnamnet. Till exempel kan det överordnade elementet StackPanel
i det pågående StackPanel
/ Button
-exemplet registrera en hanterare för det underordnade elementets Click-händelse genom att ange attributet Button.Click
på StackPanel
-objektelementet, med ditt hanterarnamn som attributvärde. Mer information finns i Översikt över routade händelser.
Som standard har objektinstansen som skapas i ett objektdiagram genom bearbetning av ett XAML-objektelement ingen unik identifierare eller objektreferens. Om du däremot anropar en konstruktor i kod använder du nästan alltid konstruktorresultatet för att ange en variabel till den konstruerade instansen, så att du kan referera till instansen senare i koden. För att ge standardiserad åtkomst till objekt som har skapats via en markeringsdefinition definierar XAML attributet x:Name. Du kan ange värdet för attributet x:Name
för alla objektelement. I koden bakom motsvarar den identifierare du väljer en instansvariabel som refererar till den konstruerade instansen. I alla avseenden fungerar namngivna element som om de vore objektinstanser (namnet refererar till den instansen) och din kod bakom kan referera till de namngivna elementen för att hantera körningsinteraktioner i appen. Den här anslutningen mellan instanser och variabler utförs av WPF XAML-kompilatorn och omfattar mer specifikt funktioner och mönster som InitializeComponent som inte beskrivs i detalj i den här artikeln.
WPF-XAML-element på ramverksnivå ärver en Name egenskap, vilket motsvarar det XAML-definierade x:Name
-attributet. Vissa andra klasser tillhandahåller också egenskapsnivåekvivalenter för x:Name
, som också vanligtvis definieras som en Name
egenskap. Om du inte hittar en Name
egenskap i medlemstabellen för det valda elementet/typen använder du vanligtvis x:Name
i stället.
x:Name
-värdena ger en identifierare till ett XAML-element som kan användas vid körning, antingen av specifika undersystem eller av verktygsmetoder som FindName.
I följande exempel anges Name på ett StackPanel element. Sedan refererar en hanterare på Button inom StackPanel till StackPanel via instansreferensen buttonContainer
som angivet av Name.
<StackPanel Name="buttonContainer">
<Button Click="RemoveThis_Click">Click to remove this button</Button>
</StackPanel>
private void RemoveThis_Click(object sender, RoutedEventArgs e)
{
var element = (FrameworkElement)e.Source;
if (buttonContainer.Children.Contains(element))
buttonContainer.Children.Remove(element);
}
Private Sub RemoveThis_Click(sender As Object, e As RoutedEventArgs)
Dim element = DirectCast(e.Source, FrameworkElement)
If buttonContainer.Children.Contains(element) Then
buttonContainer.Children.Remove(element)
End If
End Sub
Precis som en variabel styrs XAML-namnet för en instans av ett omfångsbegrepp, så att namn kan framtvingas vara unika inom ett visst omfång som är förutsägbart. Den primära markering som definierar en sida anger ett unikt XAML-namnskop, där XAML-namnskopgränsen är rotelementet på den sidan. Andra markeringskällor kan dock interagera med en sida vid körning, till exempel formatmallar eller mallar i formatmallar, och sådana markeringskällor har ofta egna XAML-namnskop som inte nödvändigtvis ansluter till sidans XAML-namnskop. Mer information om x:Name
och XAML-namnskop finns i Name, x:Name Directiveeller WPF XAML Namescopes.
XAML anger en språkfunktion som gör att vissa egenskaper eller händelser kan anges för alla element, även om egenskapen eller händelsen inte finns i typens definitioner för elementet som den anges på. Egenskapsversionen av den här funktionen kallas för en bifogad egenskap, händelseversionen kallas för en bifogad händelse. Konceptuellt kan du tänka på bifogade egenskaper och kopplade händelser som globala medlemmar som kan ställas in på alla XAML-element/objektinstanser. Det elementet/-klassen eller en större infrastruktur måste dock ha stöd för en lagringsplats för de bifogade värdena.
Anslutna egenskaper i XAML används vanligtvis via attributsyntax. I attributsyntax anger du en bifogad egenskap i formuläret ownerType.propertyName
.
Ytligt sett liknar detta en egenskapselementanvändning, men i det här fallet är den ownerType
du anger alltid en annan typ än objektelementet där den anslutna egenskapen anges.
ownerType
är den typ som tillhandahåller de åtkomstmetoder som krävs av en XAML-processor för att hämta eller ange det anslutna egenskapsvärdet.
Det vanligaste scenariot för kopplade egenskaper är att göra det möjligt för barnelement att överföra ett egenskapsvärde till förälderelementet.
Följande exempel illustrerar den bifogade egenskapen DockPanel.Dock. Klassen DockPanel definierar åtkomsterna för DockPanel.Dock och äger den bifogade egenskapen. Klassen DockPanel innehåller även logik som itererar dess underordnade element och specifikt kontrollerar varje element efter ett angivet värde för DockPanel.Dock. Om ett värde hittas används det värdet under layouten för att placera de underordnade elementen. Användning av den DockPanel.Dock kopplade egenskapen och den här positioneringsfunktionen är i själva verket det motiverande scenariot för klassen DockPanel.
<DockPanel>
<Button DockPanel.Dock="Left" Width="100" Height="20">I am on the left</Button>
<Button DockPanel.Dock="Right" Width="100" Height="20">I am on the right</Button>
</DockPanel>
I WPF implementeras de flesta eller alla anslutna egenskaper också som beroendeegenskaper. För mer information, se översikten över bifogade egenskaper.
Kopplade händelser använder en liknande ownerType.eventName
form av attributsyntax. Precis som de icke-kopplade händelserna anger attributvärdet för en bifogad händelse i XAML namnet på den hanteringsmetod som anropas när händelsen hanteras på elementet. Kopplade händelseanvändningar i WPF XAML är mindre vanliga. Mer information finns i översikten över kopplade händelser.
Underliggande WPF XAML och dess XAML-namnområde är en samling typer som motsvarar CLR-objekt och markeringselement för XAML. Alla klasser kan dock inte mappas till element. Abstrakta klasser, till exempel ButtonBaseoch vissa icke-abstrakta basklasser, används för arv i CLR-objektmodellen. Basklasser, inklusive abstrakta, är fortfarande viktiga för XAML-utveckling eftersom vart och ett av de konkreta XAML-elementen ärver medlemmar från någon basklass i hierarkin. Ofta innehåller dessa medlemmar egenskaper som kan anges som attribut för elementet eller händelser som kan hanteras. FrameworkElement är den konkreta basgränssnittsklassen för WPF på WPF-ramverksnivå. När du utformar användargränssnittet använder du olika form-, panel-, dekoratörs- eller kontrollklasser, som alla härleds från FrameworkElement. En relaterad basklass, FrameworkContentElement, stöder dokumentorienterade element som fungerar bra för en flödeslayoutpresentation med hjälp av API:er som avsiktligt speglar API:erna i FrameworkElement. Kombinationen av attribut på elementnivå och en CLR-objektmodell ger dig en uppsättning vanliga egenskaper som kan anges för de flesta konkreta XAML-element, oavsett det specifika XAML-elementet och dess underliggande typ.
XAML är ett markeringsspråk som direkt representerar instansiering och körning av objekt. Därför har element som skapats i XAML samma möjlighet att interagera med systemresurser (t.ex. nätverksåtkomst, filsystem-I/O) som appkoden gör. XAML har också samma åtkomst till systemresurserna som värdappen.
Till skillnad från .NET Framework har WPF för .NET inte stöd för CAS. Mer information finns i skillnader i kodåtkomstsäkerhet.
XAML kan användas för att definiera hela användargränssnittet, men det är ibland också lämpligt att definiera en del av användargränssnittet i XAML. Den här funktionen kan användas för att:
- Aktivera partiell anpassning.
- Lokal lagring av användargränssnittsinformation.
- Modellera ett affärsobjekt.
Nyckeln till dessa scenarier är klassen XamlReader och dess Load metod. Indatafilen är en XAML-fil och utdata är ett objekt som representerar hela körningsträdet av objekt som skapades från den markeringen. Sedan kan du infoga objektet som en egenskap för ett annat objekt som redan finns i appen. Så länge egenskapen finns i innehållsmodellen och har visningsfunktioner som meddelar körningsmotorn att nytt innehåll har lagts till i appen, kan du enkelt ändra innehållet i en app som körs genom att dynamiskt läsa in i XAML.
Feedback om .NET Desktop feedback
.NET Desktop feedback är ett öppen källkod projekt. Välj en länk för att ge feedback: