Xamarin.FormsMarcado de C# C# markup

Descargar ejemplo Descargar el ejemploDownload Sample Download the sample

El marcado de C# es un conjunto opcional de métodos y clases auxiliares fluidas para simplificar el proceso de creación de interfaces de usuario declarativas Xamarin.Forms en C#.C# markup is an opt-in set of fluent helper methods and classes to simplify the process of building declarative Xamarin.Forms user interfaces in C#. La API fluida proporcionada por el marcado de C# está disponible en el Xamarin.Forms.Markup espacio de nombres.The fluent API provided by C# markup is available in the Xamarin.Forms.Markup namespace.

Al igual que con XAML, el marcado de C# permite una separación limpia entre el marcado de la interfaz de usuario y la lógica de la interfaz de usuario.Just as with XAML, C# markup enables a clean separation between UI markup and UI logic. Esto se puede lograr separando el marcado de la interfaz de usuario y la lógica de la interfaz de usuario en archivos de clase parcial distintos.This can be achieved by separating UI markup and UI logic into distinct partial class files. Por ejemplo, para una página de inicio de sesión, el marcado de la interfaz de usuario se encontraba en un archivo denominado LoginPage.CS, mientras que la lógica de la interfaz de usuario se encontraba en un archivo denominado LoginPage.Logic.CS.For example, for a login page the UI markup would be in a file named LoginPage.cs, while the UI logic would be in a file named LoginPage.logic.cs.

El marcado de C# está disponible en Xamarin.Forms 4,6.C# markup is available from Xamarin.Forms 4.6. Sin embargo, actualmente es experimental y solo se puede usar agregando la siguiente línea de código al archivo app.CS :However, it's currently experimental and can only be used by adding the following line of code to your App.cs file:

Device.SetFlags(new string[]{ "Markup_Experimental" });

Nota

El marcado de C# está disponible en todas las plataformas admitidas por Xamarin.Forms .C# markup is available on all the platforms supported by Xamarin.Forms.

Ejemplo básicoBasic example

En el ejemplo siguiente se muestra cómo establecer el contenido de la página en un nuevo Grid que contiene un Label y un Entry , en C#:The following example shows setting the page content to a new Grid containing a Label and an Entry, in C#:

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;

En este ejemplo se crea un Grid objeto, Label con Entry objetos secundarios y.This example creates a Grid object, with child Label and Entry objects. LabelMuestra el texto y los Entry datos se enlazan a la RegistrationCode propiedad del ViewModel.The Label displays text, and the Entry data binds to the RegistrationCode property of the viewmodel. Cada vista secundaria se establece para que aparezca en una fila específica de Grid , y Entry abarca todas las columnas de Grid .Each child view is set to appear in a specific row in the Grid, and the Entry spans all the columns in the Grid. Además, se establece el alto de Entry , junto con el teclado, los colores, el tamaño de fuente del texto y su Margin .In addition, the height of the Entry is set, along with its keyboard, colors, the font size of its text, and its Margin. Por último, la Page.Content propiedad se establece en el Grid objeto.Finally, the Page.Content property is set to the Grid object.

El marcado de C# permite que este código se vuelva a escribir mediante su API fluida:C# markup enables this code to be re-written using its fluent API:

using Xamarin.Forms.Markup;
using static Xamarin.Forms.Markup.GridRowsColumns;

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 } .Font (15)
               .Row (BodyRow.CodeEntry) .ColumnSpan (All<BodyCol>()) .Margin (fieldMargin) .Height (44)
               .Bind (nameof(vm.RegistrationCode))
  }
}};

Este ejemplo es idéntico al ejemplo anterior, pero la API fluida de marcado en C# simplifica el proceso de creación de la interfaz de usuario en C#.This example is identical to the previous example, but the C# markup fluent API simplifies the process of building the UI in C#.

Nota

El marcado de C# incluye métodos de extensión que establecen propiedades específicas de la vista.C# markup includes extension methods that set specific view properties. Estos métodos de extensión no están diseñados para reemplazar todos los establecedores de propiedad.These extension methods are not meant to replace all property setters. En su lugar, están diseñados para mejorar la legibilidad del código y se pueden usar en combinación con los establecedores de propiedad.Instead, they are designed to improve code readability, and can be used in combination with property setters. Se recomienda usar siempre un método de extensión cuando exista uno para una propiedad, pero puede elegir el saldo que prefiera.It's recommended to always use an extension method when one exists for a property, but you can choose your preferred balance.

Enlace de datosData binding

El marcado de C# incluye un Bind método de extensión, junto con sobrecargas, que crea un enlace de datos entre una propiedad de vista enlazable y una propiedad especificada.C# markup includes a Bind extension method, along with overloads, that creates a data binding between a view bindable property and a specified property. El Bind método conoce la propiedad enlazable predeterminada para la mayoría de los controles que se incluyen en Xamarin.Forms .The Bind method knows the default bindable property for the majority of the controls that are included in Xamarin.Forms. Por lo tanto, normalmente no es necesario especificar la propiedad de destino al utilizar este método.Therefore, it's typically not necessary to specify the target property when using this method. Sin embargo, también puede registrar la propiedad enlazable predeterminada para controles adicionales:However, you can also register the default bindable property for additional controls:

using Xamarin.Forms.Markup;
//...

DefaultBindableProperties.Register(HoverButton.CommandProperty, RadialGauge.ValueProperty);

El Bind método se puede utilizar para enlazar a cualquier propiedad enlazable:The Bind method can be used to bind to any bindable property:

using Xamarin.Forms.Markup;
// ...

new Label { Text = "No data available" }
           .Bind (Label.IsVisibleProperty, nameof(vm.Empty))

Además, el BindCommand método de extensión se puede enlazar al valor predeterminado Command y a las propiedades de un control CommandParameter en una única llamada al método:In addition, the BindCommand extension method can bind to a control's default Command and CommandParameter properties in a single method call:

using Xamarin.Forms.Markup;
// ...

new TextCell { Text = "Tap me" }
              .BindCommand (nameof(vm.TapCommand))

De forma predeterminada, CommandParameter se enlaza al contexto de enlace.By default, the CommandParameter is bound to the binding context. También puede especificar la ruta de acceso de enlace y el origen de los Command CommandParameter enlaces y:You can also specify the binding path and source for the Command and the CommandParameter bindings:

using Xamarin.Forms.Markup;
// ...

new TextCell { Text = "Tap Me" }
              .BindCommand (nameof(vm.TapCommand), vm, nameof(Item.Id))

En este ejemplo, el contexto de enlace es una Item instancia de, por lo que no es necesario especificar un origen para el Id CommandParameter enlace.In this example, the binding context is an Item instance, so you don't need to specify a source for the Id CommandParameter binding.

Si solo necesita enlazar a Command , puede pasar null al parameterPath argumento del BindCommand método.If you only need to bind to Command, you can pass null to the parameterPath argument of the BindCommand method. Como alternativa, use el Bind método.Alternatively, use the Bind method.

También puede registrar las propiedades y predeterminadas Command CommandParameter para los controles adicionales:You can also register the default Command and CommandParameter properties for additional controls:

using Xamarin.Forms.Markup;
//...

DefaultBindableProperties.RegisterCommand(
    (CustomViewA.CommandProperty, CustomViewA.CommandParameterProperty),
    (CustomViewB.CommandProperty, CustomViewB.CommandParameterProperty)
);

El código de convertidor en línea se puede pasar al Bind método con convert los convertBack parámetros y:Inline converter code can be passed into the Bind method with the convert and convertBack parameters:

using Xamarin.Forms.Markup;
//...

new Label { Text = "Tree" }
           .Bind (Label.MarginProperty, nameof(TreeNode.TreeDepth),
                  convert: (int depth) => new Thickness(depth * 20, 0, 0, 0))

También se admiten los parámetros de convertidor Safe Type:Type safe converter parameters are also supported:

using Xamarin.Forms.Markup;
//...

new Label { }
           .Bind (nameof(viewModel.Text),
                  convert: (string text, int repeat) => string.Concat(Enumerable.Repeat(text, repeat)))

Además, el código y las instancias del convertidor se pueden volver a usar con la FuncConverter clase:In addition, converter code and instances can be re-used with the FuncConverter class:

using Xamarin.Forms.Markup;
//...

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),

La FuncConverter clase también admite CultureInfo objetos:The FuncConverter class also supports CultureInfo objects:

using Xamarin.Forms.Markup;
//...

cultureAwareConverter = new FuncConverter<DateTimeOffset, string, int>(
    (date, daysToAdd, culture) => date.AddDays(daysToAdd).ToString(culture)
);

También es posible enlazar datos a Span objetos que se especifican con la FormattedText propiedad:It's also possible to data bind to Span objects that are specified with the FormattedText property:

using Xamarin.Forms.Markup;
//...

new Label { } .FormattedText (
    new Span { Text = "Built with " },
    new Span { TextColor = Color.Blue, TextDecorations = TextDecorations.Underline }
              .BindTapGesture (nameof(vm.ContinueToCSharpForMarkupCommand))
              .Bind (nameof(vm.Title))
)

Reconocedores de gestosGesture recognizers

Command``CommandParameterlas propiedades y pueden ser datos enlazados a GestureElement View tipos y mediante los BindClickGesture métodos de BindSwipeGesture extensión, y BindTapGesture :Command and CommandParameter properties can be data bound to GestureElement and View types using the BindClickGesture, BindSwipeGesture, and BindTapGesture extension methods:

using Xamarin.Forms.Markup;
//...

new Label { Text = "Tap Me" }
           .BindTapGesture (nameof(vm.TapCommand))

En este ejemplo se crea un reconocedor de gestos del tipo especificado y se agrega a Label .This example creates a gesture recognizer of the specified type, and adds it to the Label. Los Bind*Gesture métodos de extensión ofrecen los mismos parámetros que los BindCommand métodos de extensión.The Bind*Gesture extension methods offer the same parameters as the BindCommand extension methods. Sin embargo, de forma predeterminada no se Bind*Gesture enlaza CommandParameter , mientras que BindCommand sí.However, by default Bind*Gesture does not bind CommandParameter, while BindCommand does.

Para inicializar un reconocedor de gestos con parámetros, use los ClickGesture métodos de extensión,, PanGesture PinchGesture , SwipeGesture y TapGesture :To initialize a gesture recognizer with parameters, use the ClickGesture, PanGesture, PinchGesture, SwipeGesture, and TapGesture extension methods:

using Xamarin.Forms.Markup;
//...

new Label { Text = "Tap Me" }
           .TapGesture (g => g.Bind(nameof(vm.DoubleTapCommand)).NumberOfTapsRequired = 2)

Dado que un reconocedor de gestos es un BindableObject , puede utilizar los Bind BindCommand métodos de extensión y al inicializarlo.Since a gesture recognizer is a BindableObject, you can use the Bind and BindCommand extension methods when you initialize it. También puede inicializar tipos de reconocedor de gestos personalizados con el Gesture<TGestureElement, TGestureRecognizer> método de extensión.You can also initialize custom gesture recognizer types with the Gesture<TGestureElement, TGestureRecognizer> extension method.

DiseñoLayout

El marcado de C# incluye una serie de métodos de extensión de diseño que admiten la colocación de vistas en diseños y contenido en vistas:C# markup includes a series of layout extension methods that support positioning views in layouts, and content in views:

TipoType Métodos de extensiónExtension methods
FlexLayout AlignSelf, Basis, Grow, Menu, Order, ShrinkAlignSelf, Basis, Grow, Menu, Order, Shrink
Grid Row, Column, RowSpan, ColumnSpanRow, Column, RowSpan, ColumnSpan
Label TextLeft, TextCenterHorizontal, TextRightTextLeft, TextCenterHorizontal, TextRight
TextTop, TextCenterVertical, TextBottomTextTop, TextCenterVertical, TextBottom
TextCenter
Layout Padding, PaddingsPadding, Paddings
LayoutOptions Left, CenterHorizontal, FillHorizontal, RightLeft, CenterHorizontal, FillHorizontal, Right
LeftExpand, CenterExpandHorizontal, FillExpandHorizontal, RightExpandLeftExpand, CenterExpandHorizontal, FillExpandHorizontal, RightExpand
Top, Bottom, CenterVertical, FillVerticalTop, Bottom, CenterVertical, FillVertical
TopExpand, BottomExpand, CenterExpandVertical, FillExpandVerticalTopExpand, BottomExpand, CenterExpandVertical, FillExpandVertical
Center, Fill, CenterExpand, FillExpandCenter, Fill, CenterExpand, FillExpand
View Margin, MarginsMargin, Margins
VisualElement Height, Width, MinHeight, MinWidth, Size, MinSizeHeight, Width, MinHeight, MinWidth, Size, MinSize

Compatibilidad de izquierda a derecha y de derecha a izquierdaLeft-to-right and right-to-left support

En el marcado de C# diseñado para admitir la dirección de flujo de izquierda a derecha (LTR) o de derecha a izquierda (RTL), los métodos de extensión enumerados anteriormente ofrecen el conjunto de nombres más intuitivo Left : Right , Top y Bottom .For C# markup that is designed to support either left-to-right (LTR) or right-to-left (RTL) flow direction, the extension methods listed above offer the most intuitive set of names: Left, Right, Top and Bottom.

Para que esté disponible el conjunto correcto de métodos de extensión izquierdo y derecho y, en el proceso, haga que sea explícito en qué dirección de flujo está diseñada el marcado, incluya una de las dos using directivas siguientes: using Xamarin.Forms.Markup.LeftToRight; , o using Xamarin.Forms.Markup.RightToLeft; .To make the correct set of left and right extension methods available, and in the process make explicit which flow direction the markup is designed for, include one of the following two using directives: using Xamarin.Forms.Markup.LeftToRight;, or using Xamarin.Forms.Markup.RightToLeft;.

En el marcado de C# diseñado para admitir la dirección de flujo de izquierda a derecha y de derecha a izquierda, se recomienda usar los métodos de extensión en la tabla siguiente, en lugar de uno de los espacios de nombres anteriores:For C# markup that is designed to support both left-to-right and right-to-left flow direction, it's recommended to use the extension methods in the following table rather than either of the above namespaces:

TipoType Métodos de extensiónExtension methods
Label TextStart, TextEndTextStart, TextEnd
LayoutOptions Start, EndStart, End
StartExpand, EndExpandStartExpand, EndExpand

Convención de línea de diseñoLayout line convention

La Convención recomendada es colocar todos los métodos de extensión de diseño para una vista en una sola línea en el orden siguiente:The recommended convention is to put all the layout extension methods for a view on a single line in the following order:

  1. La fila y la columna que contienen la vista.The row and column that contain the view.
  2. Alineación dentro de la fila y la columna.Alignment within the row and column.
  3. Márgenes alrededor de la vista.Margins around the view.
  4. Tamaño de la vista.View size.
  5. Relleno dentro de la vista.Padding within the view.
  6. Alineación del contenido dentro del relleno.Content alignment within the padding.

En el código siguiente se muestra un ejemplo de esta Convención:The following code shows an example of this convention:

new Label { }
           .Row (BodyRow.Prompt) .ColumnSpan (All<BodyCol>()) .FillExpandHorizontal () .CenterVertical () .Margin (fieldNameMargin) .TextCenterHorizontal () // Layout line

De forma coherente, la Convención le permite leer rápidamente el marcado de C# y crear una asignación mental de la ubicación en la que se encuentra el contenido de la vista en la interfaz de usuario.Consistently following the convention enables you to quickly read C# markup and build a mental map of where the view content is located in the UI.

Filas y columnas de cuadrículaGrid rows and columns

Las enumeraciones se pueden utilizar para definir Grid filas y columnas, en lugar de usar números.Enumerations can be used to define Grid rows and columns, instead of using numbers. Esto ofrece la ventaja de que la renumeración no es necesaria al agregar o quitar filas o columnas.This offers the advantage that renumbering is not required when adding or removing rows or columns.

Importante

GridLa definición de filas y columnas mediante enumeraciones requiere la siguiente using Directiva:using static Xamarin.Forms.Markup.GridRowsColumns;Defining Grid rows and columns using enumerations requires the following using directive: using static Xamarin.Forms.Markup.GridRowsColumns;

En el código siguiente se muestra un ejemplo de cómo definir y consumir Grid filas y columnas mediante enumeraciones:The following code shows an example of how to define and consume Grid rows and columns using enumerations:

using Xamarin.Forms.Markup;
using Xamarin.Forms.Markup.LeftToRight;
using static Xamarin.Forms.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     , 160 ),
        (BodyCol.FieldValidation, Star)
    ),

    Children =
    {
        new Label { LineBreakMode = LineBreakMode.WordWrap } .Font (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 } .Font (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)),
    }
};

Además, puede definir de manera concisa filas y columnas sin enumeraciones:In addition, you can concisely define rows and columns without enumerations:

new Grid
{
    RowDefinitions = Rows.Define (Auto, Star, 20),
    ColumnDefinitions = Columns.Define (Auto, Star, 20, 40)
    // ...
}

FuentesFonts

Los controles de la lista siguiente pueden llamar a FontSize los Bold métodos de extensión,, Italic y Font para establecer la apariencia del texto que muestra el control:The controls in the following list can call the FontSize, Bold, Italic, and Font extension methods to set the appearance of the text displayed by the control:

  • Button
  • DatePicker
  • Editor
  • Entry
  • Label
  • Picker
  • SearchBar
  • Span
  • TimePicker

EfectosEffects

Los efectos se pueden adjuntar a los controles con el Effect método de extensión:Effects can be attached to controls with the Effect extension method:

using Xamarin.Forms.Markup;
// ...

new Button { Text = "Tap Me" }
            .Effects (new ButtonMixedCaps())

Integración de lógicaLogic integration

El Invoke método de extensión se puede usar para ejecutar código insertado en el marcado de C#:The Invoke extension method can be used to execute code inline in your C# markup:

using Xamarin.Forms.Markup;
// ...

new ListView { } .Invoke (l => l.ItemTapped += OnListViewItemTapped)

Además, puede usar el método de Assign extensión para tener acceso a un control desde fuera del marcado de la interfaz de usuario (en el archivo de lógica de la interfaz de usuario):In addition, you can use the Assign extension method to access a control from outside the UI markup (in the UI logic file):

using Xamarin.Forms.Markup;
// ...

new ListView { } .Assign (out MyListView)

EstilosStyles

En el ejemplo siguiente se muestra cómo crear estilos implícitos y explícitos mediante el marcado de C#:The following example shows how to create implicit and explicit styles using C# markup:

using Xamarin.Forms.Markup;
using Xamarin.Forms;

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
    }
}

Los estilos implícitos se pueden consumir cargándolo en el Diccionario de recursos de la aplicación:The implicit styles can be consumed by loading them into the application resource dictionary:

public App()
{
    Resources = Styles.Implicit;
    // ...
}

Los estilos explícitos se pueden usar con el Style método de extensión.Explicit styles can be consumed with the Style extension method.

using static CSharpForMarkupExample.Styles;
// ...

new Button { Text = "Tap Me" } .Style (FilledButton),

Nota

Además del método de Style extensión, también hay métodos de ApplyToDerivedTypes extensión,, BasedOn Add y CanCascade .In addition to the Style extension method, there are also ApplyToDerivedTypes, BasedOn, Add, and CanCascade extension methods.

Como alternativa, puede crear sus propios métodos de extensión de estilo:Alternatively, you can create your own styling extension methods:

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;
}

El Filled método de extensión se puede consumir de la siguiente manera:The Filled extension method can then be consumed as follows:

new Button { Text = "Tap Me" } .Filled ()

Características específicas de las plataformasPlatform-specifics

El Invoke método de extensión se puede usar para aplicar características específicas de la plataforma.The Invoke extension method can be used to apply platform-specifics. Sin embargo, para evitar errores de ambigüedad, no incluya using directivas para los Xamarin.Forms.PlatformConfiguration.*Specific espacios de nombres directamente.However, to avoid ambiguity errors, don't include using directives for the Xamarin.Forms.PlatformConfiguration.*Specific namespaces directly. En su lugar, cree un alias de espacio de nombres y consuma los específicos de la plataforma mediante el alias:Instead, create a namespace alias and consume the platform-specific via the alias:

using Xamarin.Forms.Markup;
using PciOS = Xamarin.Forms.PlatformConfiguration.iOSSpecific;
// ...

new ListView { } .Invoke (l => PciOS.ListView.SetGroupHeaderStyle(l, PciOS.GroupHeaderStyle.Grouped))

Además, si usa ciertos específicos de la plataforma con frecuencia, puede crear métodos de extensión fluida para ellos en su propia clase de extensiones:In addition, if you consume certain platform-specifics frequently you can create fluent extension methods for them in your own extensions class:

public static T iOSGroupHeaderStyle<T>(this T listView, PciOS.GroupHeaderStyle style) where T : Forms.ListView
{
  PciOS.ListView.SetGroupHeaderStyle(listView, style);
  return listView;
}

El método de extensión se puede consumir de la siguiente manera:The extension method can then be consumed as follows:

new ListView { } .iOSGroupHeaderStyle(PciOS.GroupHeaderStyle.Grouped)

Para obtener más información sobre las características específicas de la plataforma, vea características de la plataforma Android, características de la plataforma iOSy características de la plataforma Windows.For more information about platform-specifics, see Android platform features, iOS platform features, and Windows platform features.

Un orden recomendado y una agrupación de propiedades y métodos auxiliares es:A recommended order and grouping of properties and helper methods is:

  • Propósito: cualquier propiedad o método auxiliar cuyo valor identifique el propósito del control (por ejemplo Text ,, Placeholder Assign ).Purpose: any property or helper methods whose value identifies the control's purpose (e.g. Text, Placeholder, .Assign).
  • Otros: todas las propiedades o métodos auxiliares que no son de diseño ni de enlace, en la misma línea o en varias líneas.Other: all properties or helper methods that are not layout or binding, on the same line or multiple lines.
  • Diseño: el diseño se ordena de forma ascendente: filas y columnas, opciones de diseño, margen, tamaño, relleno y alineación del contenido.Layout: layout is ordered inwards: rows and columns, layout options, margin, size, padding, and content alignment.
  • BIND: el enlace de datos se realiza al final de la cadena de métodos, con una propiedad enlazada por línea.Bind: data binding is performed at the end of the method chain, with one bound property per line. Si la propiedad enlazable predeterminada está enlazada, debe estar al final de la cadena de métodos.If the default bindable property is bound, it should be at the end of the method chain.

En el código siguiente se muestra un ejemplo de la siguiente Convención:The following code shows an example of following this convention:

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

Aplicar de forma coherente esta Convención permite examinar rápidamente el marcado de C# y compilar una imagen mental del diseño de la interfaz de usuario.Consistently applying this convention enables you to quickly scan your C# markup and build a mental image of the UI layout.