Contrôles personnalisés dans le Designer Xamarin pour iOS

Le Designer Xamarin pour iOS prend en charge le rendu des contrôles personnalisés créés dans votre projet ou référencés à partir de sources externes telles que le magasin de composants Xamarin.

Avertissement

Le Designer iOS a été déprécié dans Visual Studio 2019 version 16.8 et Visual Studio 2019 pour Mac version 8.8, puis supprimé dans Visual Studio 2019 version 16.9 et Visual Studio pour Mac version 8.9. La méthode recommandée pour créer des interfaces utilisateur iOS est directement sur un Mac exécutant Xcode. Pour plus d’informations, consultez Conception d’interfaces utilisateur avec Xcode.

Le Designer Xamarin pour iOS est un outil puissant pour visualiser l’interface utilisateur d’une application et fournit la prise en charge de l’édition WYSIWYG pour la plupart des vues et des contrôleurs de vue iOS. Votre application peut également contenir des contrôles personnalisés qui étendent ceux intégrés à iOS. Si ces contrôles personnalisés sont écrits avec quelques instructions à l’esprit, ils peuvent également être rendus par le Designer iOS, offrant ainsi une expérience d’édition encore plus riche. Ce document examine ces recommandations.

Spécifications

Un contrôle qui répond à toutes les exigences suivantes est affiché sur l’aire de conception :

  1. Il s’agit d’une sous-classe directe ou indirecte d’UIView ou UIViewController. D’autres sous-classes NSObject s’affichent sous la forme d’une icône sur l’aire de conception.
  2. Il a un RegisterAttribute pour l’exposer à Objective-C.
  3. Il a le constructeur IntPtr requis.
  4. Il implémente l’interface IComponent ou a un DesignTimeVisibleAttribute défini sur True.

Les contrôles définis dans le code qui répondent aux exigences ci-dessus s’affichent dans le concepteur lorsque leur projet conteneur est compilé pour le simulateur. Par défaut, tous les contrôles personnalisés apparaissent dans la section Composants personnalisés de la boîte à outils. Toutefois, l’attribut CategoryAttribute peut être appliqué à la classe du contrôle personnalisé pour spécifier une section différente.

Le concepteur ne prend pas en charge le chargement de bibliothèques tierces Objective-C .

Propriétés personnalisées

Une propriété déclarée par un contrôle personnalisé s’affiche dans le panneau de propriétés si les conditions suivantes sont remplies :

  1. La propriété a un getter et un setter publics.
  2. La propriété a un ExportAttribute ainsi qu’un BrowsableAttribute défini sur True.
  3. Le type de propriété est un type numérique, un type énumération, chaîne, bool, SizeF, UIColor ou UIImage. Cette liste des types pris en charge peut être étendue à l’avenir.

La propriété peut également être décorée d’un DisplayNameAttribute pour spécifier l’étiquette qui s’affiche pour elle dans le panneau de propriétés.

Initialisation

Pour UIViewController les sous-classes, vous devez utiliser la méthode ViewDidLoad pour le code qui dépend des vues que vous avez créées dans le concepteur.

Pour UIView et d’autres NSObject sous-classes, la méthode AwakeFromNib est l’emplacement recommandé pour effectuer l’initialisation de votre contrôle personnalisé après son chargement à partir du fichier de disposition. Cela est dû au fait que toutes les propriétés personnalisées définies dans le panneau de propriétés ne seront pas définies lors de l’exécution du constructeur du contrôle, mais elles seront définies avant AwakeFromNib d’être appelées :

[Register ("CustomView"), DesignTimeVisible (true)]
public class CustomView : UIView {

    public CustomView (IntPtr handle) : base (handle) { }

    public override void AwakeFromNib ()
    {
        // Initialize the view here.
    }
}

Si le contrôle est également conçu pour être créé directement à partir du code, vous pouvez créer une méthode qui a un code d’initialisation commun, comme suit :

[Register ("CustomView"), DesignTimeVisible (true)]
public class CustomView : UIView {

    public CustomView (IntPtr handle) : base (handle) { }

    public CustomView ()
    {
        // Called when created from code.
        Initialize ();
    }

    public override void AwakeFromNib ()
    {
        // Called when loaded from xib or storyboard.
        Initialize ();
    }

    void Initialize ()
    {
        // Common initialization code here.
    }
}

Initialisation de propriété et AwakeFromNib

Il faut veiller à savoir quand et où initialiser des propriétés pouvant être définies dans un composant personnalisé afin de ne pas remplacer les valeurs qui ont été définies à l’intérieur de l’Designer iOS. Par exemple, prenez le code suivant :

[Register ("CustomView"), DesignTimeVisible (true)]
public class CustomView : UIView {

    [Export ("Counter"), Browsable (true)]
    public int Counter {get; set;}

    public CustomView (IntPtr handle) : base (handle) { }

    public CustomView ()
    {
        // Called when created from code.
        Initialize ();
    }

    public override void AwakeFromNib ()
    {
        // Called when loaded from xib or storyboard.
        Initialize ();
    }

    void Initialize ()
    {
        // Common initialization code here.
        Counter = 0;
    }
}

Le CustomView composant expose une Counter propriété qui peut être définie par le développeur dans le Designer iOS. Toutefois, quelle que soit la valeur définie à l’intérieur du concepteur, la valeur de la Counter propriété est toujours égale à zéro (0). Voici pourquoi :

  • Une instance de est CustomControl gonflée à partir du fichier Storyboard.
  • Toutes les propriétés modifiées dans le concepteur iOS sont définies (par exemple, en définissant la valeur de sur Counter deux (2), par exemple).
  • La AwakeFromNib méthode est exécutée et un appel est effectué à la méthode du Initialize composant.
  • La Initialize valeur de la Counter propriété est réinitialisée à zéro (0).

Pour résoudre la situation ci-dessus, initialisez la Counter propriété ailleurs (par exemple, dans le constructeur du composant) ou ne remplacez pas la AwakeFromNib méthode et appelez Initialize si le composant ne nécessite aucune initialisation supplémentaire en dehors de ce qui est actuellement géré par ses constructeurs.

Mode Création

Sur l’aire de conception, un contrôle personnalisé doit respecter quelques restrictions :

  • Les ressources de l’offre groupée d’applications ne sont pas disponibles en mode création. Les images sont disponibles lorsqu’elles sont chargées via les méthodes UIImage .
  • Les opérations asynchrones, telles que les requêtes web, ne doivent pas être effectuées en mode création. L’aire de conception ne prend pas en charge l’animation ou d’autres mises à jour asynchrones de l’interface utilisateur du contrôle.

Un contrôle personnalisé peut implémenter IComponent et utiliser la propriété DesignMode pour case activée s’il se trouve sur l’aire de conception. Dans cet exemple, l’étiquette affiche « Mode Création » sur l’aire de conception et « Runtime » au moment de l’exécution :

[Register ("DesignerAwareLabel")]
public class DesignerAwareLabel : UILabel, IComponent {

    #region IComponent implementation

    public ISite Site { get; set; }
    public event EventHandler Disposed;

    #endregion

    public DesignerAwareLabel (IntPtr handle) : base (handle) { }

    public override void AwakeFromNib ()
    {
        if (Site != null && Site.DesignMode)
            Text = "Design Mode";
        else
            Text = "Runtime";
    }
}

Vous devez toujours case activée la Site propriété pour null avant d’essayer d’accéder à l’un de ses membres. Si Site a la valeur null, il est prudent de supposer que le contrôle n’est pas en cours d’exécution dans le concepteur. En mode création, Site est défini après l’exécution du constructeur du contrôle et avant AwakeFromNib l’appel.

Débogage

Un contrôle qui répond aux exigences ci-dessus s’affiche dans la boîte à outils et s’affiche sur la surface. Si un contrôle n’est pas rendu, case activée pour les bogues dans le contrôle ou l’une de ses dépendances.

L’aire de conception peut souvent intercepter les exceptions levées par des contrôles individuels tout en continuant à afficher d’autres contrôles. Le contrôle défectueux est remplacé par un espace réservé rouge, et vous pouvez afficher la trace d’exception en cliquant sur l’icône d’exclamation :

Un contrôle défectueux en tant qu’espace réservé rouge et les détails de l’exception

Si des symboles de débogage sont disponibles pour le contrôle, la trace aura des noms de fichiers et des numéros de ligne. Si vous double-cliquez sur une ligne dans la trace de pile, vous accédez à cette ligne dans le code source.

Si le concepteur ne peut pas isoler le contrôle défectueux, un message d’avertissement s’affiche en haut de l’aire de conception :

Message d’avertissement en haut de l’aire de conception

Le rendu complet reprend lorsque le contrôle défectueux est fixe ou supprimé de l’aire de conception.

Résumé

Cet article a présenté la création et l’application de contrôles personnalisés dans le concepteur iOS. Tout d’abord, il a décrit les exigences que les contrôles doivent respecter pour être affichés sur l’aire de conception et exposer des propriétés personnalisées dans le panneau de propriétés. Il a ensuite examiné le code derrière - initialisation du contrôle et la propriété DesignMode. Enfin, il décrit ce qui se passe lorsque des exceptions sont levées et comment résoudre ce problème.