Mai 2019

Volume 34, numéro 5

[XAML]

Contrôles XAML personnalisés

Par Jerry Nixon

En tant que développeur en entreprise, vous connaissez SQL Server à votre rythme. Vous savez que les services Web .NET. Et, pour vous, concevez de magnifiques interfaces XAML (probablement avec Windows Presentation Foundation (WPF)) est un jeu d’enfant. Comme des milliers d’autres développeurs de carrière, votre curriculum vitae de remplissage des technologies Microsoft et découper les articles de MSDN Magazine similaire à celle-ci et de les épingler à votre tableau Kanban. Obtenir votre ciseaux, cet article est une base.

Il est temps pour améliorer votre expertise avec les contrôles XAML. L’infrastructure XAML offre une importante bibliothèque de contrôles pour le développement de l’interface utilisateur, mais pour faire ce que vous voulez, vous devez bien plus encore. Dans cet article je vous montrerai comment obtenir les résultats souhaités à l’aide de contrôles personnalisés de XAML.

Contrôles personnalisés

Il existe deux approches de création de contrôles personnalisés dans XAML : les contrôles utilisateur et des contrôles. Les contrôles utilisateur sont une approche simple et convivial de concepteur à la création d’une disposition réutilisable. Contrôles basés sur des modèles offrent une disposition flexible avec une API personnalisable pour les développeurs. Comme c’est le cas dans n’importe quel langage, des dispositions sophistiquées peuvent produire des milliers de lignes de XAML qui peut être difficile de naviguer de manière productive. Les contrôles personnalisés sont une stratégie efficace pour réduire le code de mise en page.

Choix de l’approche correcte aura un impact sur la réussite vous pouvez utiliser et réutiliser les contrôles dans votre application. Voici quelques considérations pour vous aider à commencer.

Simplicité. Opération simple n’est pas toujours simple, mais simple est toujours facile. Contrôles utilisateur sont simples et faciles. Les développeurs sur n’importe quel niveau peuvent distribuer avec peu de portée pour la documentation.

Expérience de conception. De nombreux développeurs aiment le concepteur XAML. Dispositions de contrôle basé sur un modèle peuvent être générées dans le concepteur, mais il s’agit du contrôle utilisateur qui englobe l’expérience au moment du design.

Surface d’API. Création d’une surface API intuitive permet aux développeurs de facilement le consommer. Contrôles utilisateur prend en charge les propriétés personnalisées, des événements et des méthodes, mais des contrôles sont les plus flexibles.

Éléments visuels flexibles. En fournissant une expérience par défaut excellent permet aux développeurs de consommer des contrôles en toute simplicité. Mais les contrôles flexibles prennent en charge les éléments visuels de re-basé sur un modèle. Seuls les contrôles basés sur des modèles prennent en charge les re-création de modèles.

En résumé, les contrôles utilisateur sont optimales pour une expérience de conception et de simplicité, tandis que les contrôles basés sur des modèles vous donnent de la surface d’API meilleures et les visuels plus souples.

Si vous décidez de démarrer avec un contrôle utilisateur et migrer vers un contrôle basé sur un modèle, vous avez un travail qui vous attend. Mais, il n’est pas terminal. Cet article commence par un contrôle utilisateur et se déplace vers un contrôle basé sur un modèle. Il est important de reconnaître que nombreuses dispositions réutilisables nécessitent uniquement des contrôles utilisateur. Il est également raisonnable ouvrir une solution line-of-business et rechercher des contrôles utilisateur et des contrôles.

Un nouveau récit utilisateur

Vous devez obtenir de nouveaux utilisateurs à donner son consentement pour le contrat de licence utilisateur final (CLUF) dans votre nouvelle application. Comme vous et moi les deux le savez, aucun utilisateur ne veut donner son consentement pour un CLUF. Pourtant, juridique doit s’assurer utilisateurs Cochez « J’accepte » avant de continuer. Par conséquent, même si le CLUF est source de confusion, vous allez vous assurer de que l’interface XAML est claire et plus intuitive. Vous démarrez prototypage ; vous ajoutez un bloc de texte, une case à cocher, un bouton, comme indiqué dans Figure 1, et ensuite vous pencher.

Interface utilisateur prototypée
Interface utilisateur prototypées figure 1

Création de prototypes dans le concepteur XAML est rapide. Et il est facile, car vous avez pris le temps d’apprendre les outils. Mais qu’en est-il des autres formulaires dans votre application ? Vous devrez peut-être cette fonctionnalité ailleurs. L’encapsulation est un modèle de conception utilisé pour masquer une logique complexe du consommateur. Ne vous répétez pas (sec) en est une autre, en mettant l’accent sur la réutilisation du code.  XAML offre à la fois par les contrôles utilisateur et des contrôles personnalisés. En tant que XAML développeur, vous connaissez les contrôles personnalisés sont plus puissantes que les contrôles utilisateur, mais ils ne sont pas aussi simples. Vous décidez de démarrer avec un contrôle utilisateur. Par exemple, il peut récupérer le travail terminé. Alerte de déflecteur : Il ne peut pas.

Contrôles User

Contrôles utilisateur sont faciles. Ils fournissent des interfaces cohérentes et réutilisables et un code-behind personnalisé, encapsulé. Pour créer un contrôle utilisateur, sélectionnez contrôle utilisateur à partir de la boîte de dialogue Ajouter un nouvel élément, comme indiqué dans Figure 2.

Ajouter la boîte de dialogue Nouvel élément
Figure 2 ajouter la boîte de dialogue Nouvel élément

Les contrôles utilisateur sont généralement un enfant d’un autre contrôle. Toutefois, leur cycle de vie est similaire à celle que la valeur définie pour la propriété Window.Current.Content de windows et les pages d’un contrôle utilisateur pouvant être. Les contrôles utilisateur sont complètes, prenant en charge la gestion de l’état visuel, ressources internes et toutes autres agrafe du framework XAML. Leur création n’est pas une compromission de fonctionnalités disponibles. Mon objectif est de les réutiliser sur une page, en tirant parti de leur prise en charge pour la gestion de l’état visuel, les ressources, les styles et liaison de données. Leur implémentation XAML est simple et conviviale concepteur :

<UserControl>
  <StackPanel Padding="20">
    <TextBlock>Lorem ipsum.</TextBlock>
    <CheckBox>I agree!</CheckBox>
    <Button>Submit</Button>
  </StackPanel>
</UserControl>

Ce XAML rend mon prototype antérieures et montre à quel simple qui peut être à un contrôle utilisateur. Bien entendu, il n’est pas un comportement personnalisé encore, uniquement le comportement intégré des contrôles que je déclare.

Le texte rapide chemin d’accès CLUF est longues, par conséquent, nous allons traiter les performances de texte. TextBlock (et uniquement le TextBlock) a été optimisée pour utiliser le chemin d’accès rapide, le manque de mémoire et le rendu de l’UC. Il est conçu pour être rapide, mais je peux nuisent qui :

<TextBlock Text="Optimized" />
<TextBlock>Not optimized</TextBlock>

L’utilisation de TextBlock inline contrôles tels que < exécuter / > et < LineBreak / > interrompt l’optimisation. Les propriétés telles que CharacterSpacing, LineStackingStrategy et TextTrimming peuvent faire de même. Confus ? Il existe un test simple :

Application.Current.DebugSettings
  .IsTextPerformanceVisualizationEnabled = true;

IsTextPerformanceVisualizationEnabled est un paramètre de débogage de peu connue qui vous permet de voir quel texte dans votre application est optimisé quand vous déboguez. Si le texte n’est pas vert, il est temps à examiner.

Avec chaque nouvelle version de Windows, moins de propriétés avoir un impact sur le chemin d’accès rapide ; Toutefois, il existe toujours plusieurs qui affectent les performances négatif et de façon inattendue. Avec un peu de débogage intentionnel, ce n’est pas un problème.

Règles immuables il y a autant d’avis qu’il existe des options pour l’emplacement de la logique métier. Une règle générale place plus près les règles moins mutable au contrôle. Cela est généralement plus facile et plus rapide et optimise la facilité de maintenance.

Règles d’entreprise, par ailleurs, sont différents à partir de la validation des données. Réponse aux entrées de données et la recherche de plages numériques et de la longueur de texte sont simplement de validation. Règles régissent les types de comportement de l’utilisateur.

Par exemple, une banque a une règle d’entreprise à donner un prêt pour les clients avec un score de crédit sous une valeur particulière. Un plombier dispose d’une règle ne pas à se déplacer à un client en dehors d’un certain code postal. Les règles sont sur le comportement. Dans certains cas, les règles changent chaque jour, telles que les scores de crédit influencent les nouvelles demandes de prêts. Dans d’autres cas, les règles jamais changer, telles que la façon dont un garagiste ne fonctionnera pas jamais sur un Subaru antérieure à 2014.

Examinez à présent ces critères d’acceptation : Un utilisateur ne peut pas sur le bouton jusqu'à ce que la case à cocher est activée. Il s’agit d’une règle et il est aussi immuable comme vous pouvez obtenir. Je vais mettre en œuvre proche de mes contrôles :

<StackPanel Padding="20">
  <TextBlock>Lorem ipsum.</TextBlock>
  <CheckBox x:Name="AgreeCheckBox">I agree!</CheckBox>
  <Button IsEnabled="{Binding Path=IsChecked,
    ElementName=AgreeCheckBox}">Submit1</Button>
  <Button IsEnabled="{x:Bind Path=AgreeCheckBox.IsChecked.Value,
    Mode=OneWay}">Submit2</Button>
</StackPanel>

Dans ce code, la liaison de données répond parfaitement à mes besoins. Le bouton Submit1 utilise la liaison de données WPF (et UWP) classique. Le bouton Submit2 utilise la liaison de données UWP moderne.

Notez que dans Figure 3 prenant en charge Submit2. Est-ce droit ? Eh bien, dans le concepteur Visual Studio, la liaison de données classique a l’avantage du rendu au moment du design. Pour l’instant, liaison de données compilées (x : Bind) se produit uniquement au moment de l’exécution. Choix entre la liaison de données classique et compilé est la décision simple plus difficile que vous allez apporter. D’une part, la liaison compilée est rapide. Toutefois, sur la liaison d’autres, classique est simple. Liaison compilée existe pour le problème de performances difficile du XAML de l’adresse : liaison de données. Étant donné que la liaison classique requiert la réflexion de runtime, il est naturellement plus lent, des difficultés à l’échelle.

Implémentation d’une règle d’entreprise avec la liaison de données
Figure 3 implémentation d’une règle d’entreprise avec la liaison de données

Nombreuses nouvelles fonctionnalités ont été ajoutées à la liaison classique, telles que la liaison asynchrone ; et plusieurs modèles ont émergé pour aider les développeurs. Pourtant, comme UWP postured pour réussir WPF, il souffrait du même problème de glissement. Voici quelque chose de réfléchir à : La possibilité d’utiliser la liaison classique en mode asynchrone n’a pas a été déplacée vers UWP à partir de WPF. Qui est lue ce que vous voulez, mais elle y contribue aux développeurs d’entreprise à investir dans une liaison compilée. Liaison compilée s’appuie sur le Générateur de code XAML, le code-behind les créent automatiquement et de couplage les instructions de liaison avec les propriétés réel et les types de données attendu au moment de l’exécution.

En raison de cette association, les types incompatibles peuvent créer des erreurs, comme vous pouvez la tentative de liaison à des objets anonymes ou des objets JSON dynamiques. Ces cas limites ne sont pas manqués par de nombreux développeurs, mais elles disparus :

  • Liaison compilée résout les problèmes de performances de liaison de données tout en introduisant certaines contraintes.
  • Compatibilité descendante maintient la prise en charge de la liaison classique tout en donnant aux développeurs UWP une meilleure option.
  • L’innovation et les améliorations apportées à la liaison de données sont investies dans une liaison compilée, liaison non classique.
  • Fonctionnalités telles que la liaison de fonction sont uniquement disponibles avec liaison compilée où la stratégie de liaison de Microsoft vise clairement.

Encore la simplicité et au moment du design prennent en charge de classique liaison conserve l’argument actif, en appuyant sur Microsoft developer équipe des outils pour continuer à améliorer la liaison compilée et son expérience des développeurs. Notez que dans cet article, en choisissant une ou l’autre aura un impact quasi incommensurable. Certains exemples seront illustrent la liaison classique tandis que d’autres apparaissent liaison compilée. C’est à vous de décider. La décision, bien sûr, est plus explicite dans les grandes applications.

Événements personnalisés événements personnalisés ne peuvent pas être déclarés dans XAML, afin de les gérer dans votre code-behind. Par exemple, je peux transférer l’événement click du bouton Envoyer à un événement click personnalisé sur mon contrôle utilisateur :

public event RoutedEventHandler Click;
public MyUserControl1()
{
  InitializeComponent();
  SubmitButton.Click += (s, e)
    => Click?.Invoke(this, e);
}

Ici, le code déclenche les événements personnalisés, le RoutedEventArgs de transfert à partir du bouton. Consomme les développeurs permettre gérer ces événements de façon déclarative, comme tous les autres événements dans XAML :

<controls:MyUserControl1 Click="MyUserControl1_Click" />

La valeur est que les développeurs consommateurs sont inutile d’apprendre un nouveau paradigme ; contrôles personnalisés et contrôles de premier tiers hors de la zone fonctionnellement ont le même comportement.

Propriétés personnalisées pour permettre aux développeurs consommateurs de fournir leurs propres CLUF, je peux définir l’attribut x : FieldModifier, sur le contrôle TextBlock. Cela modifie le comportement de compilation XAML à partir de la valeur private par défaut :

<TextBlock x:Name="EulaTextBlock" x:FieldModifier="public" />

Mais facile ne signifie pas bon. Cette méthode offre peu d’abstraction et oblige les développeurs à comprendre la structure interne. Elle requiert également le code-behind. Par conséquent, j’ai éviterez à l’aide de l’approche d’attributs dans ce cas :

public string Text
{
  get => (string)GetValue(TextProperty);
  set => SetValue(TextProperty, value);
}
public static readonly DependencyProperty TextProperty =
  DependencyProperty.Register(nameof(Text), typeof(string),
    typeof(MyUserControl1), new PropertyMetadata(string.Empty));

Tout aussi facile et sans les mises en garde, est une propriété de dépendance lié aux données à la propriété Text de TextBlock. Cela permet au développeur de consommation de lire, écrire ou de la liaison à la propriété de texte personnalisée :

<StackPanel Padding="20">
  <TextBlock Text="{x:Bind Text, Mode=OneWay}" />
  <CheckBox>I agree!</CheckBox>
  <Button>Submit</Button>
</StackPanel>

La propriété de dépendance est nécessaire pour prendre en charge la liaison de données. Contrôles robustes prennent en charge les cas d’utilisation de base comme la liaison de données. En outre, la propriété de dépendance n'ajoute qu’une seule ligne à ma base de code :

<TextBox Text="{x:Bind Text, Mode=TwoWay,
  UpdateSourceTrigger=PropertyChanged}" />

Liaison de données bidirectionnelle pour les propriétés personnalisées dans les contrôles utilisateur est prise en charge sans INotifyPropertyChanged. Il s’agit, car les propriétés de dépendance déclenchent des événements de modifiées internes qui surveille l’infrastructure de liaison. C’est son propre type de INotifyPropertyChanged.

Le code précédent, nous rappelle que UpdateSourceTrigger détermine lorsque des modifications sont enregistrées. Les valeurs possibles sont Explicit, LostFocus et PropertyChanged. Ce dernier se produit lorsque des modifications sont apportées.

Obstacles la consommation développeur peut souhaiter définir la propriété de contenu du contrôle utilisateur. Il s’agit d’une approche intuitive, mais il n’est pas pris en charge par les contrôles utilisateur. La propriété est déjà définie pour le XAML que j’ai déclaré :

<Controls:MyUserControl>
  Lorem Ipsum
</Controls:MyUserControl>

Cette syntaxe remplace la propriété de contenu : le TextBlock, la case à cocher et le bouton. Si je considère re-création de modèles à un cas d’usage XAML base, mon contrôle utilisateur ne parvient pas à fournir une expérience complète et robuste. Contrôles utilisateur sont faciles, mais offrent peu de contrôle ou d’extensibilité. Une syntaxe intuitive et la prise en charge de re-création de modèles font partie d’une expérience commune. Il est temps à prendre en compte un contrôle basé sur un modèle.

Contrôles basés sur des modèles

XAML a constaté des améliorations très grande consommation de mémoire, les performances, d’accessibilité et la cohérence visuelle. Les développeurs l’aiment XAML, car il est flexible. Des contrôles sont un cas particulier.

Contrôles basé sur un modèle peuvent définir quelque chose de complètement nouveau, mais existe généralement un composite de plusieurs des contrôles. L’exemple présenté ici d’un TextBlock, la case à cocher et le bouton est ensemble un scénario classique.

Par ailleurs, ne confondez pas les contrôles basés sur des modèles avec des contrôles personnalisés. Un contrôle basé sur un modèle est une disposition personnalisée. Un contrôle personnalisé est simplement une classe héritant d’un contrôle existant sans n’importe quel style personnalisé. Parfois, si vous avez besoin une méthode supplémentaire ou une propriété sur un contrôle existant, les contrôles personnalisés sont une option intéressante ; leurs visuels et logique sont déjà en place et vous êtes en étendant simplement notre.

Modèle de contrôle disposition d’un contrôle est définie par un ControlTemplate. Cette ressource spéciale est appliquée au moment de l’exécution. Chaque zone et le bouton se trouvent dans le ControlTemplate. Modèle d’un contrôle est facilement accessible par la propriété de modèle. Cette propriété de modèle n’est pas en lecture seule. Les développeurs peuvent affectez-lui un ControlTemplate personnalisé, transformer les éléments visuels d’un contrôle et le comportement pour répondre à leurs besoins spécifiques. C’est la puissance de re-création de modèles :

<ControlTemplate>
  <StackPanel Padding="20">
    <ContentControl Content="{TemplateBinding Content}" />
    <CheckBox>I agree!</CheckBox>
    <Button>Submit1</Button>
  </StackPanel>
</ControlTemplate>

ControlTemplate XAML se présente comme toute autre déclaration de mise en page. Dans le code précédent, notez que l’extension de balisage TemplateBinding spéciale. Cette liaison particulière est réglée pour les opérations de modèle unidirectionnel. Depuis Windows 10 version 1809, syntaxe de x : Bind est prise en charge dans les définitions de ControlTemplate de UWP. Ainsi, performantes, compilée, bidirectionnelle et liaisons de fonction dans les modèles. TemplateBinding fonctionne très bien dans la plupart des cas.

Generic.XAML pour créer un contrôle basé sur un modèle, sélectionnez contrôle basé sur un modèle dans la boîte de dialogue Ajouter un nouvel élément. Cela introduit trois fichiers : le fichier XAML. son code-behind ; et themes/generic.xaml, qui contient le ControlTemplate. Le fichier themes/generic.xaml est identique à WPF. Il est particulier. L’infrastructure fusionne avec les ressources de votre application automatiquement. Ressources définies ici sont repérées au niveau de l’application :

<Style TargetType="controls:MyControl">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="controls:MyControl" />
    </Setter.Value>
  </Setter>
</Style>

ControlTemplates sont appliqués à l’aide de styles implicites : styles sans une clé. Styles explicites ont une clé utilisée pour les appliquer aux contrôles ; styles implicites sont appliquées en fonction TargetType. Par conséquent, vous devez définir DefaultStyleKey :

public sealed class MyControl : Control
{
  public MyControl() => DefaultStyleKey = typeof(MyControl);
}

Ce code définit le DefaultStyleKey, déterminer quel style est implicitement appliqué à votre contrôle. Je suis lui affectant la valeur correspondante de TargetType dans le ControlTemplate :

<ControlTemplate TargetType="controls:MyControl">
  <StackPanel Padding="20">
    <TextBlock Text="{TemplateBinding Text}" />
    <CheckBox Name="AgreeCheckbox">I agree!</CheckBox>
    <Button IsEnabled="{Binding IsChecked,
      ElementName=AgreeCheckbox}">Submit</Button>
  </StackPanel>
</ControlTemplate>

TemplateBinding lie la propriété Text de TextBlock à la propriété de dépendance personnalisée copiée à partir du contrôle utilisateur dans le contrôle basé sur un modèle. TemplateBinding est unidirectionnelle, très efficace et généralement la meilleure option.

Figure 4 montre le résultat de mon travail dans le concepteur. La disposition personnalisée déclarée dans le ControlTemplate est appliquée à mon contrôle personnalisé, et la liaison est exécutée et restituée au moment du design :

 

<controls:MyControl Text="My outside value." />

Afficher un aperçu en toute transparence à l’aide des propriétés internes
Aperçu de la figure 4 en toute transparence à l’aide des propriétés internes

La syntaxe à utiliser mon contrôle personnalisé est simple. Je vais en faire une meilleure en permettant au développeur d’utiliser un texte inséré. Il s’agit de la syntaxe la plus intuitive pour définir le contenu d’un élément. XAML fournit un attribut de classe pour m’aider à le faire, en tant que Figure 5 montre.

Figure 5 à l’aide de l’attribut de classe pour définir la propriété de contenu

[ContentProperty(Name = "Text")]
public sealed class MyControl : Control
{
  public MyControl() => DefaultStyleKey = typeof(MyControl);
  public string Text
  {
    get => (string)GetValue(TextProperty);
    set => SetValue(TextProperty, value);
  }
  public static readonly DependencyProperty TextProperty =
    DependencyProperty.Register(nameof(Text), typeof(string),
      typeof(MyControl), new PropertyMetadata(default(string)));
}

Notez que l’attribut ContentProperty, qui provient de l’espace de noms Windows.UI.Xaml.Markup. Il indique dans quelle propriété directe, le contenu inclus déclaré dans XAML doit être écrit. Par conséquent, à présent, je peux déclare mon contenu comme suit :

<controls:MyControl>
  My inline value!
</controls:MyControl>

C'est beau. Contrôles basés sur des modèles vous donnent la possibilité de concevoir une interaction de contrôle et de syntaxe dans la façon la plus vous semble intuitive. Figure 6 montre le résultat de l’introduction ContentProperty au contrôle.

Aperçu de la conception
Figure 6 Design Preview

Le ContentControl où précédemment, j’ai dû créer une propriété personnalisée et mapper cette propriété pour le contenu du contrôle, XAML fournit un contrôle déjà créé pour ce faire. Il est appelé ContentControl et sa propriété est appelée contenu. ContentControl fournit également les propriétés ContentTemplate et jouer pour gérer la visualisation et transitions. Bouton, de case à cocher, de Frame et de nombreux contrôles XAML standards héritent ContentControl. Mien peut comporter, trop ; J’utiliserais simplement le contenu plutôt que du texte :

public sealed class MyControl2 : ContentControl
{
  // Empty
}

Dans ce code, notez la syntaxe laconique pour créer un contrôle personnalisé avec une propriété de contenu. ContentControl automatique-affiche un ContentPresenter lorsque déclaré. C’est une solution rapide et facile. Il existe un inconvénient, toutefois : ContentControl ne prend pas en charge les chaînes littérales dans XAML. Parce qu’il viole mon objectif pour rendre mon contrôle prennent en charge les chaînes littérales, je m’en tiendrai au contrôle, envisagez de ContentControl un autre moment.

L’accès à des contrôles internes la directive x : Name déclare le nom de champ généré automatiquement dans un code-behind. Donner une case à cocher x : Name de MyCheckBox et le générateur crée un champ dans votre classe appelée MyCheckBox.

Par contraste, x : Key (uniquement pour des ressources) ne crée pas un champ. Il ajoute des ressources à un dictionnaire des types non résolus jusqu'à ce qu’ils sont tout d’abord utilisés. Pour les ressources, x : Key améliore les performances.

Étant donné que x : Name crée un champ de stockage, il ne peut pas être utilisé dans un ControlTemplate ; les modèles sont dissociés de n’importe quelle classe de stockage. Au lieu de cela, vous utilisez la propriété de nom.

Nom est une propriété de dépendance sur FrameworkElement, un ancêtre du contrôle. Utilisez-le lorsque vous ne pouvez pas utiliser x : Name. Nom et x : Name s’excluent mutuellement dans l’étendue donnée en raison de FindName.

FindName est une méthode XAML utilisée pour localiser des objets par nom ; il fonctionne avec le nom ou x : Name. Il est fiable dans le code-behind, mais pas dans des contrôles où vous devez utiliser GetTemplateChild :

protected override void OnApplyTemplate()
{
  if (GetTemplateChild("AgreeCheckbox") is CheckBox c)
  {
    c.Content = "I really agree!";
  }
}

GetTemplateChild est une méthode d’assistance utilisée dans la substitution de OnApplyTemplate pour rechercher des contrôles créés par un ControlTemplate. Il permet de rechercher des références à des contrôles internes.

La modification du modèle Re-création de modèles du contrôle est simple, mais j’ai créé la classe pour attendre que les contrôles portant certains noms. Je dois m’assurer que le nouveau modèle gère cette dépendance. Commençons par créer un nouveau modèle de contrôle :

<ControlTemplate
  TargetType="controls:MyControl"
  x:Key="MyNewStyle">

Modifications mineures à un ControlTemplate sont normale. Vous n’avez pas besoin de démarrer à partir de zéro. Dans le volet Structure du Document Visual Studio, avec le bouton droit n’importe quel contrôle et extraire une copie de son modèle actuel (consultez Figure 7).

Extraction d’un modèle de contrôle
Figure 7 extraire un modèle de contrôle

Si je gère ses dépendances, mon nouveau ControlTemplate peut totalement changer les éléments visuels et les comportements d’un contrôle. Déclaration d’un style explicite sur le contrôle indique à l’infrastructure pour ignorer le style implicite par défaut :

<controls:MyControl Style="{StaticResource MyControlNewStyle}">

Mais cette réécriture de ControlTemplate est fourni avec un avertissement. Les développeurs et concepteurs de contrôles doivent être prudent prendre en charge des fonctionnalités d’accessibilité et la localisation. Il est facile de les supprimer par erreur.

TemplatePartAttribute serait pratique si un contrôle personnalisé capable de communiquer les éléments nommés, il attend. Certains éléments nommés peuvent être nécessaire uniquement pendant les cas extrêmes. Dans WPF, vous avez TemplatePartAttribute :

[TemplatePart (
  Name = "EulaTextBlock",
  Type = typeof(TextBlock))]
public sealed class MyControl : Control { }

Cette syntaxe montre comment le contrôle peut communiquer les dépendances internes pour les développeurs externes. Dans ce cas, j’attends un TextBlock avec le nom EulaTextBlock dans mon ControlTemplate. Je peux également spécifier les états visuels que m’attendre dans mon contrôle personnalisé :

[TemplateVisualState(
  GroupName = "Visual",
  Name = "Mouseover")]
public sealed class MyControl : Control { }

TemplatePart est utilisé par Blend avec TemplateVisualState pour aider les développeurs aux prévisions lors de la création de modèles personnalisés. Un ControlTemplate peut être validé par rapport à ces attributions. Depuis 10240, WinRT a inclus ces attributs. UWP permettre les utiliser, mais ne Blend pour Visual Studio. Ils restent une pratique bon, blogue, mais documentation est toujours la meilleure approche.

Accessibilité les contrôles internes XAML sont méticuleusement conçus et testés pour être superbe, compatible et accessible. Critères d’accessibilité sont désormais citoyens de première classe et sont les exigences de version pour chaque contrôle.

Lorsque vous re-modèle un contrôle internes, vous placez au risque les fonctionnalités d’accessibilité réfléchie ajoutées par les équipes de développement. Ils sont difficiles à obtenir le droit et simple de se tromper. Lorsque vous choisissez pour re-modèle un contrôle, vous devez être rompus dans les fonctionnalités d’accessibilité de l’infrastructure et les techniques pour les implémenter. Sinon, vous perdez une grande partie de leur valeur.

Ajout d’accessibilité comme une exigence de version permet non seulement ceux présentant un handicap permanent, mais aussi celles qui sont temporairement un. Elle réduit également les risques lorsque des contrôles de re-création de modèles internes.

Tu as réussi !

Après la mise à niveau à partir d’un contrôle utilisateur à un contrôle basé sur un modèle, j’ai présenté très peu de code nouveau. Mais j’ai ajouté un grand nombre de fonctionnalités. Prenons l’exemple ce qui a été accompli globale.

Encapsulation. Le contrôle est constitué de plusieurs contrôles, fourni avec les visuels personnalisés et les comportements que beaucoup de développeurs peuvent réutiliser facilement dans une application.

Logique métier. Le contrôle incorpore des règles d’entreprise qui remplissent les critères d’acceptation du récit utilisateur. J’ai des règles immuable proche du contrôle et prise en charge d’une riche expérience au moment du design, trop.

Événements personnalisés. Le contrôle expose des événements personnalisés spécifiques au contrôle comme « clic » qui aident les développeurs interagissent avec le contrôle, sans avoir à comprendre la structure interne de la disposition.

Propriétés personnalisées. Le contrôle expose les propriétés pour permettre au développeur de consommation influencer le contenu de la disposition. Il s’agit de manière à prendre entièrement en charge la liaison de données XAML.

Syntaxe d’API. Le contrôle prend en charge une approche intuitive qui permet aux développeurs de déclarer leur contenu avec des chaînes littérales et d’une manière simple. J’ai exploité l’attribut ContentProperty pour ce faire.

Modèles. Le contrôle est livré avec une valeur par défaut ControlTemplate qui dispose d’une interface intuitive. Toutefois, XAML re-création de modèles est pris en charge pour permettre aux développeurs de consommateur personnaliser les éléments visuels en fonction des besoins.

Il est plus à faire

Mon contrôle a besoin de plus, mais pas beaucoup plus — juste un peu d’attention à disposition (par exemple, la nécessité de faire défiler le texte de grande taille) et quelques propriétés (par exemple, le contenu de la case à cocher). Je suis étonnamment fermer.

Contrôles peuvent prendre en charge la gestion de l’état visuel, une fonctionnalité native de XAML qui permet des propriétés à modifier en fonction de dimensionnement des événements de framework (par exemple, mouseover). Les contrôles matures ont des états visuels.

Contrôles peuvent prendre en charge la localisation ; la fonctionnalité native dans UWP utilise les contrôles association directive x : Uid avec des chaînes RESW qui sont filtrés par les paramètres régionaux actif. Contrôles matures prennent en charge la localisation.

Contrôles peuvent prendre en charge les définitions de style externe pour aider à mettre à jour leurs visuels sans nécessiter un nouveau modèle ; Vous pouvez impliquent des visuels partagés et tirer parti des thèmes et styles de BasedOn. Contrôles matures partagent et réutiliser des styles.

Pour résumer

Prototypage une interface utilisateur dans XAML est rapide. Contrôles utilisateur créent facilement des dispositions simples et réutilisables. Des contrôles nécessitent un peu plus de travail pour créer des dispositions simples et réutilisables avec des fonctionnalités plus sophistiquées. L’approche adéquate est au développeur, basé sur une petite base de connaissances et beaucoup d’expérience. Expérience. Plus vous découvrez les outils, le plus productif que vous allez vous.

Windows Forms a réussi à Visual Basic 6 en 2002, comme WPF a réussi à Windows Forms en 2006. WPF fait XAML : un langage déclaratif pour l’interface utilisateur. Les développeurs Microsoft avaient vu jamais rien comme XAML. Aujourd'hui, Xamarin et UWP mettre XAML pour iOS, Android, HoloLens, Surface Hub, Xbox, IoT et le poste de travail moderne. En fait, XAML est désormais la technologie de création du système d’exploitation Windows lui-même.

Les développeurs du monde adorent XAML, car il est donc productifs et flexibles. Les ingénieurs de Microsoft l’êtes aussi ; Nous créons notre propre applications et même Windows 10 avec XAML. Le futur est passionnant, les outils sont puissants et la technologie est plus facile que jamais.


Jerry Nixonest un logiciel senior ingénieur & architecte senior dans commerciale Software Engineering chez Microsoft. Il a développé et conçu logiciel depuis 20 ans. L’intervenant, organisateur, l’enseignant et auteur, Nixon est également l’hôte de DevRadio. La plupart de ses jours consacrés à l’enseigne ses trois filles backstories de « Star Trek » et les tracés d’épisode.

Merci aux experts techniques Microsoft suivants d'avoir relu cet article : Daniel Norman, Dmitry Lyalin, mai Daren, Ricardo Minguez Pablos


Discuter de cet article sur le forum MSDN Magazine