Xamarin Community Toolkit C# Markup
Xamarin.CommunityToolkit.MarkupSample herunterladen
C#-Markup ist eine Reihe von Fluent-Hilfsmethoden und -klassen, um den Prozess des Erstellens deklarativer Xamarin.Forms-Benutzeroberflächen in C# zu vereinfachen. Die fluent-API, die Xamarin.CommunityToolkit.Markup
von C#-Markup bereitgestellt wird, ist im Namespace verfügbar.
Ebenso wie bei XAML ermöglicht C#-Markup eine saubere Trennung zwischen UI-Markup und UI-Logik. Dies kann erreicht werden, indem Ui-Markup- und UI-Logik in verschiedene Teilklassendateien getrennt werden. Für eine Anmeldeseite würde sich das UI-Markup beispielsweise in einer Datei namens LoginPage.cs befinden, während sich die UI-Logik in einer Datei namens "LoginPage.logic.cs" befindet.
Die neueste Version von C#-Markup erfordert Xamarin.Forms 5 und ist im Xamarin.CommunityToolkit.Markup NuGet-Paket verfügbar.
C#-Markup ist auf allen Plattformen verfügbar, die von Xamarin.Forms unterstützt werden.
Hinweis
Die Vorschauversion des C#-Markups ist in Xamarin.Forms 4.6 bis 4.8 als experimentelles Feature verfügbar.
So migrieren Sie von der C#-Markupvorschauversion zu XCT C#-Markup:
- Aktualisieren auf Xamarin.Forms Forms 5.
- Installieren Sie das Xamarin.CommunityToolkit.Markup NuGet-Paket.
- Ändern Sie alle Verweise auf den
Xamarin.Forms.Markup
Namespace inXamarin.CommunityToolkit.Markup
, und stellen Sie sicher, dass Sie in Ihre Markupdateien einschließenusing Xamarin.Forms;
. - Aktualisieren Sie
Font
bei Bedarf Hilfsaufrufe.Font
Jetzt hatfamily
es den ersten Parameter anstelle vonsize
. Ersetzen.Font(15)
Sie z. B. durch.Font(size: 15)
oder.FontSize(15)
.
Wenn Sie bereits mit der Vorschauversion von C#-Markup vertraut sind, finden Sie weitere Funktionen im Xamarin Community Toolkit weiter unten.
Einfaches Beispiel
Das folgende Beispiel zeigt das Festlegen des Seiteninhalts auf eine neue Grid
, die ein Label
und ein Entry
, in C#enthält:
Grid grid = new Grid();
Label label = new Label { Text = "Code: " };
grid.Children.Add(label, 0, 1);
Entry entry = new Entry
{
Placeholder = "Enter number", Keyboard = Keyboard.Numeric, BackgroundColor = Color.AliceBlue, TextColor = Color.Black, FontSize = 15,
HeightRequest = 44, Margin = fieldMargin
};
grid.Children.Add(entry, 0, 2);
Grid.SetColumnSpan(entry, 2);
entry.SetBinding(Entry.TextProperty, new Binding("RegistrationCode"));
Content = grid;
In diesem Beispiel wird ein Grid
Objekt mit untergeordneten und Entry
untergeordneten Label
Objekten erstellt. Der Label
Text wird angezeigt, und die Entry
Daten werden an die RegistrationCode
Eigenschaft des Viewmodels gebunden. Jede untergeordnete Ansicht ist so festgelegt, dass sie in einer bestimmten Zeile im Grid
Bereich angezeigt wird und die Entry
alle Spalten in der Grid
. Darüber hinaus wird die Höhe des Entry
Elements festgelegt, zusammen mit seiner Tastatur, Farben, dem Schriftgrad des Texts und dessen Margin
. Schließlich wird die Page.Content
Eigenschaft auf das Grid
Objekt festgelegt.
Mit dem C#-Markup kann dieser Code mithilfe der Fluent-API erneut geschrieben werden:
Content = new Grid { Children =
{
new Label { Text = "Code:" }
.Row (BodyRow.CodeHeader) .Column (BodyCol.Header),
new Entry { Placeholder = "Enter number", Keyboard = Keyboard.Numeric, BackgroundColor = Color.AliceBlue, TextColor = Color.Black } .FontSize (15)
.Row (BodyRow.CodeEntry) .ColumnSpan (All<BodyCol>()) .Margin (fieldMargin) .Height (44)
.Bind (nameof(vm.RegistrationCode))
}}};
Dieses Beispiel ist identisch mit dem vorherigen Beispiel, aber die C#-Markup fluent-API vereinfacht den Prozess der Erstellung der Benutzeroberfläche in C#.
Hinweis
C#-Markup enthält Erweiterungsmethoden, die bestimmte Ansichtseigenschaften festlegen. Diese Erweiterungsmethoden sollen nicht alle Eigenschaftssatzer ersetzen. Stattdessen sind sie so konzipiert, dass sie die Codelesbarkeit verbessern und in Kombination mit Eigenschaftensatzern verwendet werden können. Es wird empfohlen, immer eine Erweiterungsmethode zu verwenden, wenn eine für eine Eigenschaft vorhanden ist, aber Sie können Ihr bevorzugtes Gleichgewicht auswählen.
Namespace-Verwendungen
Um C#-Markup zu verwenden, schließen Sie die folgenden using
Anweisungen in Ihre Markupdateien ein:
using Xamarin.Forms;
using Xamarin.CommunityToolkit.Markup;
Wenn Sie Ihr Markup für Folgendes entwerfen:
- NUR LTR: auch einschließen
using Xamarin.CommunityToolkit.Markup.LeftToRight;
- NUR RTL: auch einschließen
using Xamarin.CommunityToolkit.Markup.RightToLeft;
- Sowohl LTR als auch RTL: Enthalten
LeftToRight
oderRightToLeft
Namespaces nicht
Wenn Sie mit Grid
Zeilen und Spalten arbeiten möchten, schließen Sie auch dies ein using static Xamarin.CommunityToolkit.Markup.GridRowsColumns;
.
Datenbindung
C#-Markup enthält eine Bind
Erweiterungsmethode zusammen mit Überladungen, die eine Datenbindung zwischen einer bindungsfähigen Ansichtseigenschaft und einer angegebenen Eigenschaft erstellt. Die Bind
Methode kennt die Standardbindungseigenschaft für die Mehrzahl der Steuerelemente, die in Xamarin.Forms enthalten sind. Daher ist es in der Regel nicht erforderlich, die Zieleigenschaft bei Verwendung dieser Methode anzugeben. Sie können auch die Standardbindungseigenschaft für zusätzliche Steuerelemente registrieren:
DefaultBindableProperties.Register(
HoverButton.CommandProperty,
RadialGauge.ValueProperty
);
Die Bind
Methode kann verwendet werden, um an eine bindungsfähige Eigenschaft zu binden:
new Label { Text = "No data available" }
.Bind (Label.IsVisibleProperty, nameof(vm.Empty))
Darüber hinaus kann die BindCommand
Erweiterungsmethode an die Standard Command
- und CommandParameter
Eigenschaften eines Steuerelements in einem einzigen Methodenaufruf binden:
new TextCell { Text = "Tap me" }
.BindCommand (nameof(vm.TapCommand))
Standardmäßig ist die CommandParameter
Bindung an den Bindungskontext gebunden. Sie können auch den Bindungspfad und die Quelle für die Command
CommandParameter
Bindungen angeben:
new TextCell { Text = "Tap Me" }
.BindCommand (nameof(vm.TapCommand), vm, nameof(Item.Id))
In diesem Beispiel ist der Bindungskontext eine Item
Instanz, sodass Sie keine Quelle für die Id
CommandParameter
Bindung angeben müssen.
Wenn Sie nur an die Bindung binden Command
müssen, können Sie das parameterPath
Argument der BindCommand
Methode übergebennull
. Alternativ können Sie die Bind
Methode verwenden.
Sie können auch die Standard Command
- und CommandParameter
Eigenschaften für zusätzliche Steuerelemente registrieren:
DefaultBindableProperties.RegisterCommand(
(CustomViewA.CommandProperty, CustomViewA.CommandParameterProperty),
(CustomViewB.CommandProperty, CustomViewB.CommandParameterProperty)
);
Inlinekonvertercode kann mit den convert
Parametern convertBack
an die Bind
Methode übergeben werden:
new Label { Text = "Tree" }
.Bind (Label.MarginProperty, nameof(TreeNode.TreeDepth),
convert: (int depth) => new Thickness(depth * 20, 0, 0, 0))
Typsichere Konverterparameter werden ebenfalls unterstützt:
new Label { }
.Bind (nameof(viewModel.Text),
convert: (string text, int repeat) => string.Concat(Enumerable.Repeat(text, repeat)))
Darüber hinaus können Konvertercode und Instanzen mit der FuncConverter
Klasse erneut verwendet werden:
FuncConverter<int, Thickness> treeMarginConverter = new FuncConverter<int, Thickness>(depth => new Thickness(depth * 20, 0, 0, 0));
new Label { Text = "Tree" }
.Bind (Label.MarginProperty, nameof(TreeNode.TreeDepth), converter: treeMarginConverter),
Die FuncConverter
Klasse unterstützt CultureInfo
auch Objekte:
cultureAwareConverter = new FuncConverter<DateTimeOffset, string, int>(
(date, daysToAdd, culture) => date.AddDays(daysToAdd).ToString(culture)
);
Es ist auch möglich, datenbindung an Span
Objekte zu binden, die mit der FormattedText
Eigenschaft angegeben werden:
new Label { } .FormattedText (
new Span { Text = "Built with " },
new Span { TextColor = Color.Blue, TextDecorations = TextDecorations.Underline }
.BindTapGesture (nameof(vm.ContinueToCSharpForMarkupCommand))
.Bind (nameof(vm.Title))
)
Gestenerkennung
Command
und CommandParameter
Eigenschaften können datengebunden GestureElement
sein und View
Typen mithilfe der BindClickGesture
BindSwipeGesture
Methoden , und BindTapGesture
Erweiterungsmethoden:
new Label { Text = "Tap Me" }
.BindTapGesture (nameof(vm.TapCommand))
In diesem Beispiel wird eine Gesteerkennung des angegebenen Typs erstellt, und es wird der Label
. Die Bind*Gesture
Erweiterungsmethoden bieten dieselben Parameter wie die BindCommand
Erweiterungsmethoden. Standardmäßig Bind*Gesture
wird die Bindung jedoch nicht gebunden CommandParameter
, während BindCommand
dies der Fall ist.
Verwenden Sie die ClickGesture
Methoden , SwipeGesture
PanGesture
PinchGesture
TapGesture
um eine Gestenerkennung mit Parametern zu initialisieren:
new Label { Text = "Tap Me" }
.TapGesture (g => g.Bind(nameof(vm.DoubleTapCommand)).NumberOfTapsRequired = 2)
Da es sich bei einer Gestenerkennung um eine BindableObject
Geste handelt, können Sie die Bind
Methoden und BindCommand
Erweiterungsmethoden verwenden, wenn Sie sie initialisieren. Sie können auch benutzerdefinierte Gestenerkennungstypen mit der Gesture<TGestureElement, TGestureRecognizer>
Erweiterungsmethode initialisieren.
Layout
C#-Markup enthält eine Reihe von Layouterweiterungsmethoden, die die Positionierung von Ansichten in Layouts und Inhalten in Ansichten unterstützen:
type | Erweiterungsmethoden |
---|---|
FlexLayout |
AlignSelf , Basis , Grow , Menu , Order , Shrink |
Grid |
Row , Column , RowSpan , ColumnSpan |
Label |
TextLeft , TextCenterHorizontal , TextRight TextTop , TextCenterVertical , TextBottom TextCenter |
IPaddingElement (z. B. Layout ) |
Padding , Paddings |
LayoutOptions |
Left , CenterHorizontal , FillHorizontal , Right LeftExpand , CenterExpandHorizontal , FillExpandHorizontal , RightExpand Top , Bottom , CenterVertical , FillVertical TopExpand , BottomExpand , CenterExpandVertical , FillExpandVertical Center , Fill , CenterExpand , FillExpand |
View |
Margin , Margins |
VisualElement |
Height , Width , MinHeight , MinWidth , Size , MinSize |
Unterstützung von links nach rechts und rechts nach links
Für C#-Markup, das für die Unterstützung von links nach rechts (LTR) oder rechts-nach-links-Flussrichtung (RTL) ausgelegt ist, bieten die oben aufgeführten Erweiterungsmethoden den intuitivsten Satz von Namen: Left
, Right
Top
und Bottom
.
Um die richtigen Methoden für die linke und rechte Erweiterung verfügbar zu machen und im Prozess explizit festzulegen, für welche Flussrichtung das Markup ausgelegt ist, schließen Sie eine der folgenden beiden using
Direktiven ein: using Xamarin.CommunityToolkit.Markup.LeftToRight;
oder using Xamarin.CommunityToolkit.Markup.RightToLeft;
.
Für C#-Markup, das sowohl die Richtung von links nach rechts als auch von rechts nach links unterstützt, empfiehlt es sich, die Erweiterungsmethoden in der folgenden Tabelle anstelle einer der oben genannten Namespaces zu verwenden:
type | Erweiterungsmethoden |
---|---|
Label |
TextStart , TextEnd |
LayoutOptions |
Start , End StartExpand , EndExpand |
Layoutlinienkonvention
Die empfohlene Konvention besteht darin, alle Layouterweiterungsmethoden für eine Ansicht in einer einzelnen Zeile in der folgenden Reihenfolge zu platzieren:
- Die Zeile und Spalte, die die Ansicht enthält.
- Ausrichtung innerhalb der Zeile und Spalte.
- Seitenränder um die Ansicht.
- Ansichtsgröße.
- Abstand innerhalb der Ansicht.
- Inhaltsausrichtung innerhalb des Abstands.
Der folgende Code zeigt ein Beispiel für diese Konvention:
new Label { }
.Row (BodyRow.Prompt) .ColumnSpan (All<BodyCol>()) .FillExpandHorizontal () .CenterVertical () .Margin (fieldNameMargin) .TextCenterHorizontal () // Layout line
Durch konsistentes Folgen der Konvention können Sie C#-Markup schnell lesen und eine mentale Karte erstellen, auf der sich der Ansichtsinhalt in der Benutzeroberfläche befindet.
Zeilen und Spalten im Raster
Enumerationen können verwendet werden, um Zeilen und Spalten zu definieren Grid
, anstatt Zahlen zu verwenden. Dies bietet den Vorteil, dass die Neunummerierung beim Hinzufügen oder Entfernen von Zeilen oder Spalten nicht erforderlich ist.
Wichtig
Das Definieren von Grid
Zeilen und Spalten mithilfe von Enumerationen erfordert die folgende using
Direktive: using static Xamarin.CommunityToolkit.Markup.GridRowsColumns;
Der folgende Code zeigt ein Beispiel für das Definieren und Verwenden Grid
von Zeilen und Spalten mithilfe von Enumerationen:
using Xamarin.Forms;
using Xamarin.CommunityToolkit.Markup;
using Xamarin.CommunityToolkit.Markup.LeftToRight;
using static Xamarin.CommunityToolkit.Markup.GridRowsColumns;
// ...
enum BodyRow { Prompt, CodeHeader, CodeEntry, Button }
enum BodyCol { FieldLabel, FieldValidation }
View Build() => new Grid
{
RowDefinitions = Rows.Define(
(BodyRow.Prompt , 170 ),
(BodyRow.CodeHeader, 75 ),
(BodyRow.CodeEntry , Auto),
(BodyRow.Button , Auto)
),
ColumnDefinitions = Columns.Define(
(BodyCol.FieldLabel , Stars(0.5)),
(BodyCol.FieldValidation, Star)
),
Children =
{
new Label { LineBreakMode = LineBreakMode.WordWrap } .FontSize (15) .Bold ()
.Row (BodyRow.Prompt) .ColumnSpan (All<BodyCol>()) .FillExpandHorizontal () .CenterVertical () .Margin (fieldNameMargin) .TextCenterHorizontal ()
.Bind (nameof(vm.RegistrationPrompt)),
new Label { Text = "Registration code" } .Bold ()
.Row (BodyRow.CodeHeader) .Column(BodyCol.FieldLabel) .Bottom () .Margin (fieldNameMargin),
new Label { } .Italic ()
.Row (BodyRow.CodeHeader) .Column (BodyCol.FieldValidation) .Right () .Bottom () .Margin (fieldNameMargin)
.Bind (nameof(vm.RegistrationCodeValidationMessage)),
new Entry { Placeholder = "E.g. 123456", Keyboard = Keyboard.Numeric, BackgroundColor = Color.AliceBlue, TextColor = Color.Black } .FontSize (15)
.Row (BodyRow.CodeEntry) .ColumnSpan (All<BodyCol>()) .Margin (fieldMargin) .Height (44)
.Bind (nameof(vm.RegistrationCode), BindingMode.TwoWay),
new Button { Text = "Verify" } .Style (FilledButton)
.Row (BodyRow.Button) .ColumnSpan (All<BodyCol>()) .FillExpandHorizontal () .Margin (PageMarginSize)
.Bind (Button.IsVisibleProperty, nameof(vm.CanVerifyRegistrationCode))
.Bind (nameof(vm.VerifyRegistrationCodeCommand)),
}
};
Darüber hinaus können Sie Zeilen und Spalten ohne Enumerationen präzise definieren:
new Grid
{
RowDefinitions = Rows.Define (Auto, Star, 20),
ColumnDefinitions = Columns.Define (Auto, Star, 20, 40)
// ...
}
Schriftarten
Steuerelemente, die implementiert werdenIFontElement
, können die Bold
FontSize
Methoden , , und Italic
Font
Erweiterungsmethoden aufrufen, um die Darstellung des durch das Steuerelement angezeigten Texts festzulegen, z. B.:
Button
DatePicker
Editor
Entry
Label
Picker
SearchBar
Span
TimePicker
Effekte
Effekte können mit der Effects
Erweiterungsmethode an Steuerelemente angefügt werden:
new Button { Text = "Tap Me" }
.Effects (new ButtonMixedCaps())
Logikintegration
Die Invoke
Erweiterungsmethode kann verwendet werden, um Code-Inline in Ihrem C#-Markup auszuführen:
new ListView { } .Invoke (l => l.ItemTapped += OnListViewItemTapped)
Darüber hinaus können Sie mit der Assign
Erweiterungsmethode auf ein Steuerelement außerhalb des UI-Markups (in der Ui-Logikdatei) zugreifen:
new ListView { } .Assign (out MyListView)
Stile
Im folgenden Beispiel wird gezeigt, wie implizite und explizite Formatvorlagen mithilfe von C# Markup erstellt werden:
using Xamarin.Forms;
using Xamarin.CommunityToolkit.Markup;
namespace CSharpForMarkupDemos
{
public static class Styles
{
static Style<Button> buttons, filledButton;
static Style<Label> labels;
static Style<Span> link;
#region Implicit styles
public static ResourceDictionary Implicit => new ResourceDictionary { Buttons, Labels };
public static Style<Button> Buttons => buttons ?? (buttons = new Style<Button>(
(Button.HeightRequestProperty, 44),
(Button.FontSizeProperty, 13),
(Button.HorizontalOptionsProperty, LayoutOptions.Center),
(Button.VerticalOptionsProperty, LayoutOptions.Center)
));
public static Style<Label> Labels => labels ?? (labels = new Style<Label>(
(Label.FontSizeProperty, 13),
(Label.TextColorProperty, Color.Black)
));
#endregion Implicit styles
#region Explicit styles
public static Style<Button> FilledButton => filledButton ?? (filledButton = new Style<Button>(
(Button.TextColorProperty, Color.White),
(Button.BackgroundColorProperty, Color.FromHex("#1976D2")),
(Button.CornerRadiusProperty, 5)
)).BasedOn(Buttons);
public static Style<Span> Link => link ?? (link = new Style<Span>(
(Span.TextColorProperty, Color.Blue),
(Span.TextDecorationsProperty, TextDecorations.Underline)
));
#endregion Explicit styles
}
}
Die impliziten Formatvorlagen können verwendet werden, indem sie in das Anwendungsressourcenverzeichnis geladen werden:
public App()
{
Resources = Styles.Implicit;
// ...
}
Explizite Formatvorlagen können mit der Style
Erweiterungsmethode verwendet werden.
using static CSharpForMarkupExample.Styles;
// ...
new Button { Text = "Tap Me" } .Style (FilledButton),
Hinweis
Zusätzlich zur Style
Erweiterungsmethode gibt es auch ApplyToDerivedTypes
Methoden , BasedOn
Add
und CanCascade
Erweiterungsmethoden.
Alternativ können Sie ihre eigenen Formatierungserweiterungsmethoden erstellen:
public static TButton Filled<TButton>(this TButton button) where TButton : Button
{
button.Buttons(); // Equivalent to Style .BasedOn (Buttons)
button.TextColor = Color.White;
button.BackgroundColor = Color.Red;
return button;
}
Die Filled
Erweiterungsmethode kann dann wie folgt verwendet werden:
new Button { Text = "Tap Me" } .Filled ()
Plattformeigenschaften
Die Invoke
Erweiterungsmethode kann verwendet werden, um plattformspezifische Methoden anzuwenden. Um jedoch Nichtdeutigkeitsfehler zu vermeiden, enthalten using
Sie keine Richtlinien für die Xamarin.Forms.PlatformConfiguration.*Specific
Namespaces direkt. Erstellen Sie stattdessen einen Namespace-Alias und nutzen Sie die Plattformspezifische über den Alias:
using Xamarin.Forms;
using Xamarin.CommunityToolkit.Markup;
using PciOS = Xamarin.Forms.PlatformConfiguration.iOSSpecific;
// ...
new ListView { } .Invoke (l => PciOS.ListView.SetGroupHeaderStyle(l, PciOS.GroupHeaderStyle.Grouped))
Wenn Sie außerdem bestimmte plattformspezifische Methoden häufig nutzen, können Sie fließende Erweiterungsmethoden für sie in Ihrer eigenen Erweiterungsklasse erstellen:
public static T iOSGroupHeaderStyle<T>(this T listView, PciOS.GroupHeaderStyle style) where T : Forms.ListView
{
PciOS.ListView.SetGroupHeaderStyle(listView, style);
return listView;
}
Die Erweiterungsmethode kann dann wie folgt verwendet werden:
new ListView { } .iOSGroupHeaderStyle(PciOS.GroupHeaderStyle.Grouped)
Weitere Informationen zu plattformspezifischen Funktionen finden Sie unter Android-Plattformfeatures, iOS-Plattformfeatures und Windows-Plattformfeatures.
Empfohlene Konvention
Eine empfohlene Reihenfolge und Gruppierung von Eigenschaften und Hilfsmethoden ist:
- Zweck: Alle Eigenschaften- oder Hilfsmethoden, deren Wert den Zweck des Steuerelements (z. B.
Text
,Placeholder
.Assign
) identifiziert. - Andere: Alle Eigenschaften oder Hilfsmethoden, die nicht Layout oder Bindung sind, auf derselben Linie oder mehreren Zeilen.
- Layout: Layout wird nach innen angeordnet: Zeilen und Spalten, Layoutoptionen, Rand, Größe, Abstand und Inhaltsausrichtung.
- Bindung: Die Datenbindung wird am Ende der Methodenkette mit einer gebundenen Eigenschaft pro Zeile ausgeführt. Wenn die Standardbindungseigenschaft gebunden ist, sollte es sich am Ende der Methodenkette befinden.
Der folgende Code zeigt ein Beispiel für die folgenden Konventionen:
new Button { Text = "Verify" /* purpose */ } .Style (FilledButton) // other
.Row (BodyRow.Button) .ColumnSpan (All<BodyCol>()) .FillExpandHorizontal () .Margin (10) // layout
.Bind (Button.IsVisibleProperty, nameof(vm.CanVerifyRegistrationCode)) // bind
.Bind (nameof(vm.VerifyRegistrationCodeCommand)), // bind default
new Label { }
.Assign (out animatedMessageLabel) // purpose
.Invoke (label => label.SizeChanged += MessageLabel_SizeChanged) // other
.Row (BodyRow.Message) .ColumnSpan (All<BodyCol>()) // layout
.Bind (nameof(vm.Message)), // bind default
Durch die konsistente Anwendung dieser Konvention können Sie Ihr C#-Markup schnell scannen und ein mentales Bild des UI-Layouts erstellen.
Zusätzliche Funktionalität im Xamarin Community Toolkit
Im Xamarin Community Toolkit fügt C# Markup Unterstützung für:
MultiBinding
MultiConverter
BindableLayout
RelativeLayout
DynamicResource
Multi-Binding-Hilfser
Neue Überladungen des Bind
Hilfsgebers bieten Unterstützung für multibindung.
Es gibt Überladungen, die 2, 3 oder 4 Bindungen mit einem typsicheren Inlinekonverter unterstützen:
new Label { }
.Bind (Label.TextProperty,
new Binding (nameof(vm.Name)),
new Binding (nameof(vm.Score)),
((string name, bool score) v) => $"{v.name} Score: { v.score }"
)
Der Wert für alle Bindungen werden als ValueTuple
typgeschützte Elemente übergeben.
Sie können auch einen typsicheren Konverterparameter übergeben:
new Label { }
.Bind (Label.TextProperty,
new Binding (nameof(vm.Name)),
new Binding (nameof(vm.Score)),
((string name, int Score) v, bool winner) => $"{v.name} Score: { v.Score } Winner: { winner }",
converterParameter: true
)
Hier bool winner
wird der Wert aus dem converterParameter
.
Sie können eine Zwei-Wege-Konvertierung inline angeben:
new Entry { }
.Bind(Entry.TextProperty,
new Binding (nameof(vm.Emoticon)),
new Binding (nameof(vm.Repeat)),
((char emoticon, int repeat) v) => new string(v.emoticon, v.repeat),
(string emoticons) => (emoticons[0], emoticons.Length)
);
In der Funktion geben Sie dasselbe zurückValueTuple
, das Sie in der convertBack
convert
Funktion erhalten.
Sie können mehr als 4 Bindungen angeben, indem Sie einen Mehrwertkonverter übergeben:
new Label { }
.Bind(Label.TextProperty,
new List<BindingBase> {
new Binding(nameof(vm.Name)),
new Binding(nameof(vm.Score))
},
new FuncMultiConverter<string, bool>(
(object[] values, bool winner) => $"{values[0]} Score: { values[1] } Winner: { winner }"
)
)
Dies ist nicht typsicher: Sie müssen die Werte in die convert
Funktion umwandeln.
Die FuncMultiConverter
Klassen implementieren IMultiValueConverter
. Die klasse, die für eine beliebige Anzahl von Bindungen verwendet wird FuncMultiConverter<TDest, TParam>
, die nur den Zieltyp und den Parametertyp des Konvertierungsmoduls angibt. Die Bindungswerte werden als Eine object[]
übergeben.
Es gibt auch typsichere generische Überladungen für FuncMultiConverter
die 2, 3 oder 4 Werte (und optional einen Konvertierungsparameter). Diese Klassen übergeben die Bindungswerte in einem typsicheren ValueTuple
Typ .
Bindungsfähige Layouthilfen
Die EmptyView
, , ItemsSource
EmptyViewTemplate
ItemTemplate
, und ItemTemplateSelector
Hilfser bieten Unterstützung für bindungsfähige Layouts auf allen Layout<View>
Typen:
new StackLayout { }
.ItemTemplate (() =>
new Label { }
.Bind (nameof(Item.Name))
)
.ItemsSource (vm.Items)
RelativeLayout-Hilfser
Mit den Children
Hilfsern können Sie eingeschränkte untergeordnete Ansichten zu einem RelativeLayout
hinzufügen.
Um eingeschränkte Ansichten aus normalen Ansichten zu erstellen, wurden vier Hilfser hinzugefügt: Unconstrained
Constraints
und zwei Constrain
Überladungen. Jede Überladung gibt eine entsprechende *ConstrainedView
Klasse zurück, die eine Fluent-API zum Festlegen von Einschränkungen für RelativeLayout
untergeordnete Ansichten bietet.
Einschränkungen für eine untergeordnete Ansicht können mit:
- Ein einzelner Bounds-Ausdruck.
- Separate Ausdrücke für X, Y, Width und Height.
- Separate
Constraint
Instanzen für X, Y, Width und Height. Jede dieser Einschränkungsinstanzen verfügt über Überladungen für:- Konstante.
- Relativ zum übergeordneten Element.
- Relativ zur Ansicht.
Der folgende Code zeigt Beispiele für die Verwendung dieser Hilfshilfen:
new RelativeLayout { } .Children (
new Label { } // Bounds constrained
.Assign (out Label child0)
.Constrain(() => new Rectangle(30, 20, layout.Height / 2, layout.Height / 4)),
new Label { } // Expressions constrained
.Constrain() .X (() => 30)
.Y (() => 20)
.Width (() => layout.Height / 2)
.Height (() => layout.Height / 4),
new Label { } // Constraints constrained - parent relative
.Constraints() .X (30)
.Y (20)
.Width (parent => parent.Height / 5)
.Height (parent => parent.Height / 10),
new Label { } // Constraints constrained - view relative
.Constraints() .X (child0, (layout, view) => view.Bounds.Right + 10)
.Y (child0, (layout, view) => view.Y)
.Width (child0, (layout, view) => view.Width)
.Height (child0, (layout, view) => view.Height),
) .Assign (out layout)
Dynamische Ressourcenhilfen
Die Unterstützung RemoveDynamicResources
für die DynamicResource
Einstellung dynamischer Ressourcen in einem Element
: DynamicResources
new Label { }
.DynamicResource (Label.TextProperty, "TextKey")
new Label { }
.DynamicResources((Label.TextProperty , "TextKey"),
(Label.TextColorProperty, "ColorKey"));