TypeConverters och XAML
Det här avsnittet beskriver syftet med typkonvertering från sträng som en allmän XAML-språkfunktion. I .NET Framework tjänar klassen TypeConverter ett visst syfte som en del av implementeringen för en hanterad anpassad klass som kan användas som ett egenskapsvärde i XAML-attributanvändning. Om du skriver en anpassad klass och vill att instanser av klassen ska kunna användas som XAML-attributvärden kan du behöva tillämpa en TypeConverterAttribute på din klass, skriva en anpassad TypeConverter-klass eller båda.
Typkonverteringsbegrepp
XAML- och strängvärden
När du anger ett attributvärde i en XAML-fil är den första typen av det värdet en sträng i ren text. Även andra primitiver som Double är initialt textsträngar till en XAML-processor.
En XAML-processor behöver två informationsdelar för att kunna bearbeta ett attributvärde. Den första informationen är värdetypen för den egenskap som anges. Alla strängar som definierar ett attributvärde och som bearbetas i XAML måste i slutändan konverteras eller matchas till ett värde av den typen. Om värdet är en primitiv som förstås av XAML-parsern (till exempel ett numeriskt värde) görs ett direkt konverteringsförsök av strängen. Om värdet är en uppräkning används strängen för att söka efter en namnmatchning till en namngiven konstant i uppräkningen. Om värdet varken är en parser-förstådd primitiv eller en uppräkning måste typen i fråga kunna ange en instans av typen, eller ett värde, baserat på en konverterad sträng. Detta görs genom att ange en typkonverterareklass. Typkonverteraren är i själva verket en hjälpklass för att tillhandahålla värden för en annan klass, både för XAML-scenariot och även potentiellt för kodanrop i .NET-kod.
Använda befintlig typkonverteringsbeteende i XAML
Beroende på din kunskap om de underliggande XAML-begreppen kanske du redan använder typkonverteringsbeteende i grundläggande program XAML utan att inse det. Till exempel definierar WPF bokstavligen hundratals egenskaper som tar ett värde av typen Point. En Point är ett värde som beskriver en koordinat i ett tvådimensionellt koordinatutrymme, och det har egentligen bara två viktiga egenskaper: X och Y. När du anger en punkt i XAML anger du den som en sträng med en avgränsare (vanligtvis ett kommatecken) mellan de X och Y värden som du anger. Till exempel: <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"/>
.
Även den här enkla typen av Point och dess enkla användning i XAML omfattar en typkonverterare. I det här fallet är det klassen PointConverter.
Typkonverteraren för Point, som definieras på klassnivå, effektiviserar markeringsanvändningen för alla egenskaper som tar Point. Utan en typkonverterare här skulle du behöva följande mycket mer utförliga markering för samma exempel som visades tidigare:
<LinearGradientBrush>
<LinearGradientBrush.StartPoint>
<Point X="0" Y="0"/>
</LinearGradientBrush.StartPoint>
<LinearGradientBrush.EndPoint>
<Point X="1" Y="1"/>
</LinearGradientBrush.EndPoint>
</LinearGradientBrush>
Huruvida man ska använda typkonverteringssträng eller en mer utförlig motsvarande syntax är vanligtvis en stilfråga. Arbetsflödet för XAML-verktyg kan också påverka hur värden anges. Vissa XAML-verktyg tenderar att generera den mest utförliga formen av markup eftersom det är lättare att återskapa till designer-vyer eller dess egen serialiseringsmekanism.
Befintliga typkonverterare kan vanligtvis identifieras inom WPF- och .NET Framework-typer genom att kontrollera en klass (eller egenskap) för att se om en viss TypeConverterAttribute-attribut har tillämpats. Det här attributet namnger klassen som är den stödjande typkonverteraren för värden av den typen, för XAML-ändamål och potentiellt andra syften.
Typomvandlare och markup-extensions
Markeringstillägg och typkonverterare fyller ortogoniala roller när det gäller XAML-processorbeteende och de scenarier som de tillämpas på. Även om kontexten är tillgänglig för användningar av markeringstillägg, kontrolleras typkonverteringsbeteende för egenskaper där ett markeringstillägg ger ett värde i regel inte i implementeringarna av markeringstillägget. Med andra ord, även om ett markeringstillägg returnerar en textsträng som dess ProvideValue
utdata, är typkonverteringsbeteendet för strängen som tillämpas på en specifik egenskap eller egenskapsvärdetyp inte anropas. I allmänhet är syftet med ett tillägg för markering att bearbeta en sträng och returnera ett objekt utan någon typkonverterare.
En vanlig situation där ett markeringstillägg är nödvändigt i stället för en typkonverterare är att referera till ett objekt som redan finns. I bästa fall kan en tillståndslös typkonverterare bara generera en ny instans, vilket kanske inte är önskvärt. Mer information om tillägg för markering finns i Markup Extensions and WPF XAML.
Konverterare av ursprunglig typ
I WPF- och .NET Framework-implementeringen av XAML-parsern finns det vissa typer som har intern typkonverteringshantering, men som inte är typer som normalt kan betraktas som primitiver. Ett exempel på en sådan typ är DateTime. Orsaken till detta baseras på hur .NET Framework-arkitekturen fungerar: typen DateTime definieras i mscorlib, det mest grundläggande biblioteket i .NET. DateTime är inte tillåtet att hänföras till ett attribut som kommer från en annan sammansättning som introducerar ett beroende (TypeConverterAttribute är från systemet) så den vanliga mekanismen för identifiering av typkonverterare genom attributering kan inte stödjas. I stället har XAML-parsern en lista över typer som behöver sådan intern bearbetning och bearbetar dessa på samma sätt som de verkliga primitiverna bearbetas. (När det gäller DateTime innebär detta ett anrop till Parse.)
Implementera en typkonverterare
Typomvandlare
I det Point exempel som angavs tidigare nämndes klassen PointConverter. För .NET-implementeringar av XAML är alla typkonverterare som används för XAML-ändamål klasser som härleds från basklassen TypeConverter. Klassen TypeConverter fanns i versioner av .NET Framework som föregår förekomsten av XAML. en av dess ursprungliga användningar var att tillhandahålla strängkonvertering för egenskapsdialogrutor i visuella designers. För XAML utökas rollen för TypeConverter till att omfatta att vara basklassen för till-sträng- och frånsträngskonverteringar som gör det möjligt att parsa ett strängattributvärde och eventuellt bearbeta ett körningsvärde för en viss objektegenskap tillbaka till en sträng för serialisering som ett attribut.
TypeConverter definierar fyra medlemmar som är relevanta för konvertering till och från strängar för XAML-bearbetning:
Av dessa är den viktigaste metoden ConvertFrom. Den här metoden konverterar indatasträngen till den objekttyp som krävs. Strängt taget kan metoden ConvertFrom implementeras för att konvertera ett mycket bredare antal typer till konverterarens avsedda måltyp och därmed tjäna syften som sträcker sig bortom XAML, till exempel stöd för körningskonverteringar, men för XAML-ändamål är det bara kodsökvägen som kan bearbeta en String indata som är viktig.
Nästa viktigaste metod är ConvertTo. Om ett program konverteras till en markeringsrepresentation (till exempel om det sparas i XAML som en fil) ansvarar ConvertTo för att skapa en markeringsrepresentation. I det här fallet är den relevanta kodvägen för XAML när du passerar en destinationType
av String.
CanConvertTo och CanConvertFrom är supportmetoder som används när en tjänst frågar funktionerna i TypeConverter implementeringen. Du måste implementera dessa metoder för att returnera true
för typspecifika fall som motsvarande konverteringsmetoder för konverteraren stöder. För XAML-ändamål innebär detta vanligtvis den String typen.
Kulturinformation och typkonverterare för XAML
Varje TypeConverter implementering kan ha en egen tolkning av vad som utgör en giltig sträng för en konvertering och kan också använda eller ignorera den typbeskrivning som skickas som parametrar. Det finns ett viktigt övervägande när det gäller kultur- och XAML-typkonvertering. Användning av localizable-strängar som attributvärden stöds helt av XAML. Men att använda den lokaliserbara strängen som inmatning i typkonverterarens för specifika kulturkrav stöds inte, eftersom typkonverterare för XAML-attributvärden nödvändigtvis har ett beteende för fast språkanalys med hjälp av en-US
-kultur. Mer information om designorsakerna till den här begränsningen finns i XAML-språkspecifikationen ([MS-XAML].
Som ett exempel där kultur kan vara ett problem använder vissa kulturer ett kommatecken som decimalteckenavgränsare för tal. Detta kolliderar med det beteende som många av WPF XAML-typkonverterarna har, vilket är att använda ett kommatecken som avgränsare (baserat på historiska prejudikat som det vanliga X,Y-formuläret eller kommaavgränsade listor). Även om man anger en kultur i den omgivande XAML (genom att ställa in Language
eller xml:lang
till sl-SI
-kulturen, som exempelvis använder ett kommatecken som decimaltecken), löser det inte problemet.
Implementera ConvertFrom
För att kunna användas som en TypeConverter implementering som stöder XAML måste ConvertFrom-metoden för konverteraren acceptera en sträng som parametern value
. Om strängen var i giltigt format och kan konverteras av den TypeConverter implementeringen måste det returnerade objektet ha stöd för en gjutning till den typ som förväntas av egenskapen. Annars måste ConvertFrom-implementeringen returnera null
.
Varje TypeConverter implementering kan ha en egen tolkning av vad som utgör en giltig sträng för en konvertering, och kan också använda eller ignorera typbeskrivningar eller kulturkontexter som skickas som parametrar. WPF XAML-bearbetningen kanske dock inte skickar värden till typbeskrivningskontexten i alla fall och kanske inte heller skickar kultur baserat på xml:lang
.
Obs
Använd inte klammerparentestecken, särskilt {, som ett möjligt element i strängformatet. Dessa tecken är reserverade som in- och avslut för en markeringstilläggssekvens.
Implementera ConvertTo
ConvertTo kan användas för serialiseringsstöd. Serialiseringsstöd via ConvertTo för din anpassade typ och dess typkonverterare är inte ett absolut krav. Men om du implementerar en kontroll eller använder serialisering av som en del av funktionerna eller utformningen av klassen bör du implementera ConvertTo.
För att kunna användas som en TypeConverter implementering som stöder XAML måste ConvertTo-metoden för konverteraren acceptera att en instans av typen (eller ett värde) stöds som parametern value
. När parametern destinationType
är typen Stringmåste det returnerade objektet kunna gjutas som String. Den returnerade strängen måste representera ett serialiserat värde för value
. Helst bör det serialiseringsformat som du väljer kunna generera samma värde om strängen skickades till ConvertFrom implementering av samma konverterare, utan betydande informationsförlust.
Om värdet inte kan serialiseras, eller om konverteraren inte stöder serialisering, måste ConvertTo-implementeringen returnera null
och kan utlösa ett undantag i det här fallet. Men om du utlöser undantag bör du rapportera oförmågan att använda den konverteringen som en del av din CanConvertTo-implementering så att det bästa sättet att först kontrollera med CanConvertTo för att undvika undantag stöds.
Om destinationType
parametern inte är av typen Stringkan du välja din egen konverterarhantering. Vanligtvis återgår du till grundläggande implementeringshantering, vilket i det mest grundläggande ConvertTo genererar ett specifikt undantag.
Implementera CanConvertTo
Din CanConvertTo-implementation bör returnera true
för destinationType
av typen Stringoch i övrigt lämna över till basimplementationen.
Implementera CanConvertFrom
Din CanConvertFrom-implementering bör returnera true
för sourceType
av typen Stringoch annars använda basimplementeringen.
Att tillämpa TypeConverterAttribute
För att din anpassade typkonverterare ska användas som den aktiva typkonverteraren för en anpassad klass av en XAML-processor, måste du tillämpa TypeConverterAttribute på klassdefinitionen. Den ConverterTypeName som du anger via attributet måste vara typnamnet för konverteraren av anpassad typ. Med det här attributet tillämpat kan en XAML-processor hantera värden där egenskapstypen använder din anpassade klasstyp, ange strängar och returnera objektinstanser.
Du kan också tillhandahålla en typomvandlare per egenskap. I stället för att tillämpa en TypeConverterAttribute på klassdefinitionen tillämpar du den på en egenskapsdefinition (huvuddefinitionen, inte get
/set
implementeringar inom den). Egenskapens typ måste matcha den typ som bearbetas av din anpassade typkonverterare. Med det här attributet tillämpat, när en XAML-processor hanterar värden för den egenskapen, kan den bearbeta indatasträngar och returnera objektinstanser. Konverteringstekniken per egenskapstyp är särskilt användbar om du väljer att använda en egenskapstyp från Microsoft .NET Framework eller från något annat bibliotek där du inte kan styra klassdefinitionen och inte kan använda en TypeConverterAttribute där.
Se även
.NET Desktop feedback