Vue d’ensemble de la personnalisation et de la création de formulaires avec l’outil de création Service Manager
Un formulaire est une fenêtre qui permet aux utilisateurs d'interagir avec les objets à partir de la base de données. Les utilisateurs peuvent utiliser un formulaire pour afficher et modifier les propriétés des objets. Chaque formulaire est liée à une classe spécifique, et il affiche des informations uniquement pour les instances de la classe cible. Un formulaire contient des champs. En règle générale, chaque champ est lié à une propriété spécifique de la classe ciblée du formulaire. Le formulaire d'incident, par exemple, est lié à l'objet d'incident. Par conséquent, le formulaire d'incident affiche des informations sur les objets de l'incident dans la base de données.
Un formulaire Service Manager se compose de l’implémentation de formulaire Windows Presentation Foundation (WPF) dans un assembly Microsoft .NET Framework et d’une définition de formulaire dans un pack d’administration Service Manager. La définition du formulaire spécifie la classe que représente le formulaire, ainsi que les autres propriétés du formulaire.
Concepts clés sur les formulaires
Avant de personnaliser les formulaires, vous devez connaître les concepts suivants.
Utilisation des formulaires
Lorsque le pack d’administration qui contient les définitions de formulaire est importé dans Service Manager, les définitions de formulaire sont stockées dans la base de données. Plus tard, lorsque l’utilisateur lance une tâche de console Service Manager qui nécessite l’affichage d’un objet, Service Manager doit trouver un formulaire pour afficher l’objet demandé. Service Manager accède à la base de données et recherche un formulaire qui a été défini pour cet objet. Si aucun formulaire n’est défini pour l’objet, Service Manager recherche un formulaire défini pour l’objet parent de l’objet. Service Manager continue de rechercher la hiérarchie d’héritage de l’objet entier jusqu’à ce qu’il trouve un formulaire défini.
Formulaires génériques
Si Service Manager ne trouve aucun formulaire pour l’objet ou pour l’un de ses objets parents, Service Manager génère dynamiquement un formulaire générique par défaut pour cet objet. Le formulaire générique est un formulaire généré par le système qui suffit à une utilisation simple de formulaire. Le formulaire générique représente un moyen simple et rapide de créer un formulaire pour les objets sans définitions de formulaire.
Par défaut, le formulaire générique affiche toutes les propriétés du formulaire dans une disposition simple que vous ne pouvez pas modifier. Le formulaire générique affiche les propriétés de tous les objets parents dans la hiérarchie d’héritage du formulaire, et vous ne pouvez pas modifier ce comportement. Les personnalisations des formulaires génériques sont limitées. Par exemple, vous pouvez spécifier les propriétés que vous souhaitez afficher le formulaire générique ; Toutefois, le formulaire générique ne peut pas être utilisé comme base pour la personnalisation. Si vous définissez ultérieurement un formulaire personnalisé pour cet objet, votre formulaire personnalisé remplace le formulaire générique de l’objet.
Pour plus d'informations sur la possibilité de masquer les propriétés d'un formulaire générique et autres personnalisations, voir le blog Overview of the Forms Infrastructure and the Generic Form (Présentation de l'infrastructure des formulaires et du formulaire générique).
Classes combinées dans des formulaires
Il est parfois nécessaire d'afficher des informations dérivées de plusieurs classes. Pour ce faire, vous devez créer une classe de combinaison , puis lier un champ du formulaire à la classe de combinaison. Pour plus d’informations sur les classes combinées, consultez Modifications apportées au schéma commun System Center.
Aspects fonctionnels d’un formulaire
Un formulaire possède les aspects fonctionnels suivants :
Initialisation
Taille et emplacement
Actualiser
Envoi de modifications
Ces aspects sont décrits dans les sections suivantes.
Initialisation
Lors de l’initialisation, le langage XAML (Extensible Application Markup Language) d’un formulaire est analysé et tous les contrôles du formulaire sont instanciés et chargés. L’événement Loaded du formulaire indique quand le formulaire et tous les éléments contenus ont été chargés. Les opérations de chargement des données sont asynchrones. Par conséquent, l'instance cible peut ne pas être disponible lorsque l'événement Loaded est déclenché. En revanche, l'événement DataContextChanged doit être utilisé pour la notification lorsque l'instance cible est définie pour le formulaire. L'événement PropertyChanged de la propriété DataContext peut être utilisé à la place de l'événement DataContextChanged .
Il est recommandé d'utiliser l'événement Loaded pour l'initialisation personnalisée relative aux contrôles, puis d'utiliser les événements DataContextChanged ou PropertyChanged de la propriété DataContext pour l'initialisation personnalisée relative à l'instance cible.
Taille et emplacement
Lorsqu’un formulaire s’affiche dans une fenêtre contextuelle, sa taille initiale est déterminée en fonction des propriétés Width, Height, MinWidth et MinHeight du formulaire. Si ces propriétés ne sont pas définies pour le formulaire, la taille initiale du formulaire est calculée en fonction de son contenu.
Il est recommandé de définir ces propriétés comme suit :
Définissez les propriétés Width et Height du formulaire afin de spécifier explicitement la taille idéale. Envisagez d'attribuer la valeur Auto à ces propriétés. De cette façon, la largeur et la hauteur du formulaire seront définies en fonction de la taille du contenu.
Définissez les propriétés MinWidth et MinHeight du formulaire afin de spécifier la taille de fenêtre minimale pour le formulaire. Si un utilisateur redimensionne la fenêtre à une taille inférieure à celle spécifiée, des barres de défilement apparaîtront pour permettre de faire défiler le contenu de la fenêtre.
Lorsque le formulaire est hébergé à l’intérieur de l’hôte de formulaires Service Manager, la dernière taille et l’emplacement utilisés sont conservés pour l’affichage ultérieur de ce formulaire par le même utilisateur au sein de la même session d’exécution.
Actualiser
L'instance cible d'un formulaire peut changer suite à l'exécution d'une commande Refresh dans le formulaire. Le gestionnaire de cette commande récupère les nouvelles données depuis la base de données. Lorsque les données arrivent, la valeur de la propriété DataContext du formulaire est définie sur la nouvelle instance cible et l’événement DataContextChanged est déclenché.
Pour différencier l'événement DataContextChanged déclenché lors du premier chargement du formulaire, et l'événement déclenché pour la gestion d'une commande Refresh , vérifiez la propriété OldValue des arguments d'événement passés en même temps que l'événement. Cette propriété a la valeur Null si le formulaire vient d'être initialisé.
Envoi de modifications
La fenêtre contextuelle de l’hôte de formulaire dans Service Manager fournit des boutons permettant d’envoyer des modifications apportées dans le formulaire et de fermer la fenêtre contextuelle.
Lorsqu’un utilisateur sélectionne le bouton Appliquer pour un formulaire, l’instance cible du formulaire est envoyée pour le stockage. Cette opération est synchrone ; par conséquent, l’utilisateur ne peut pas modifier le formulaire tant que l’opération de soumission n’est pas terminée. En cas d'échec lors de l'envoi du formulaire, un message d'erreur s'affiche. Le formulaire reste ouvert, permettant d'apporter d'autres modifications. Il est recommandé d'appliquer les modifications fréquemment pour éviter les conflits, par exemple, si une autre instance du formulaire est modifiée en même temps.
Si l’utilisateur sélectionne le bouton OK , le comportement est similaire à Appliquer, sauf que, si l’opération de soumission de formulaire réussit, le formulaire et sa fenêtre hôte sont fermés.
Si l’utilisateur sélectionne le bouton Annuler , une boîte de dialogue s’affiche qui demande à l’utilisateur de confirmer l’opération. L’utilisateur peut sélectionner Oui et perdre les modifications, ou sélectionner Non et revenir au formulaire.
Recommandations générales et bonnes pratiques pour les formulaires
Vous pouvez étendre les fonctionnalités de Service Manager en ajoutant ou en modifiant des formulaires. Cette section décrit certaines recommandations de bonnes pratiques pour la création et l’utilisation de formulaires Service Manager, à l’aide de différents outils et définitions de formulaires de script directement.
Cette section s’adresse principalement aux partenaires et aux clients qui sont expérimentés dans la création de leurs propres formulaires personnalisés à l’aide de Windows Presentation Foundation (WPF) et de Microsoft Visual Studio Team System ou de Microsoft Expression Blend.
Les conseils d'ordre général concernant la création de nouveaux formulaires sont les suivants :
- Utilisez des contrôles standard.
- Suivez les instructions générales de conception de formulaires.
- Évitez le code-behind.
- Utilisez la gestion des exceptions.
- Envisagez la personnalisation et la mise à niveau des formulaires.
- Nommez tous les contrôles personnalisables.
- Liez le formulaire aux sources de données.
- Utilisez les règles de validation d’infrastructure de Service Manager, les converteurs de valeur et les modèles d’erreur.
- Utilisez les commandes et les événements d'infrastructure de formulaires.
Pour plus d'informations sur ces instructions, consultez les sections suivantes.
Utiliser des contrôles standard
Les contrôles utilisés dans les formulaires sont les suivants :
- Contrôles standard. Cela comprend les contrôles de bibliothèque .NET, tels que les zones de liste déroulante et les zones de liste.
- Contrôles personnalisés. Cela comprend les contrôles supplémentaires qui sont créés par l'auteur du formulaire ou par un tiers.
Conseil
En utilisant des contrôles standard et en évitant, dans la mesure du possible, de créer des contrôles personnalisés, vous garantissez la cohérence de l'expérience utilisateur. Si vous devez créer un contrôle personnalisé, séparez l'apparence et le comportement visuels du comportement logique à l'aide de modèles de contrôle permettant de définir l'apparence du contrôle. De préférence, chaque thème Windows doit posséder son propre modèle de contrôle.
Suivez les instructions générales relatives à la conception de formulaires
Lorsque vous créez un formulaire, suivez les recommandations en matière de conception afin de garantir un formulaire convivial et respectant les paradigmes courants d'interaction utilisateur.
Pour plus d'informations générales sur la conception dans Windows design, voir Windows User Experience Interaction Guidelines (Conseils en matière d'interaction et d'expérience utilisateur Windows).
De plus :
- Répartissez les informations sur plusieurs onglets pour rendre le formulaire plus simple et plus facile à lire. Incluez les informations les plus couramment utilisées sur le premier onglet et les informations de moindre importance sur les onglets suivants.
- Utilisez les panneaux de disposition pour disposer les contrôles du formulaire. Cela garantit que le formulaire se comporte correctement lorsqu’il est redimensionné et localisé.
- Évitez de définir des propriétés visuelles pour chacun des contrôles, et utilisez plutôt des styles. Cela vous permet de modifier l’apparence de tous les contrôles d’une série de formulaires en modifiant le style et favorise une apparence cohérente entre les formulaires associés.
Éviter le code-behind
Lecode-behind correspond au code joint à l'aide d'objets au balisage défini lors de la compilation du balisage d'une page XAML. Limitez autant que possible l'utilisation de code-behind dans un formulaire. Il est préférable d’incorporer le code d’un formulaire dans le contrôle lui-même, car plus tard, il est plus facile de modifier ce code. Utilisez plutôt les fonctionnalités déclaratives prises en charge par l’infrastructure de formulaires Service Manager pour définir des conversions de valeur et des règles de validation dans le formulaire.
En règle générale, vous devez limiter l’utilisation du code-behind aux situations dans lesquelles il n’est pas possible de fournir les fonctionnalités requises à l’aide des fonctionnalités déclaratives de XAML, avec des classes définies dans WPF et la bibliothèque d’infrastructure de formulaires. Même dans ce cas, envisagez de déplacer la fonctionnalité implémentée dans le code-behind vers une bibliothèque d'assistance, puis de la référencer depuis le XAML.
Inclure la gestion des exceptions
Vérifiez que le code du formulaire contient la gestion des exceptions afin que le formulaire puisse être chargé à la fois pendant la phase de conception de l’outil de création et dans la console Service Manager au moment de l’exécution.
Prendre en compte la personnalisation et les mises à niveau des formulaires
Lorsque vous concevez un nouveau formulaire, vous devez envisager de futures personnalisations et mises à niveau vers ce formulaire. Pour vous assurer qu’il est possible de personnaliser et de mettre à niveau un formulaire tout en préservant les personnalisations, suivez les instructions et conseils fournis précédemment dans cette section, ainsi que les instructions suivantes :
Envisagez les personnalisations et les mises à niveau futures dès que vous concevez le formulaire. Les formulaires sont susceptibles d’évoluer dans les versions futures, et il est important de prendre en compte la façon dont les utilisateurs pourront effectuer une mise à niveau vers de nouvelles versions de votre formulaire tout en préservant leurs personnalisations au formulaire d’origine. Par exemple, vous pouvez mettre à jour un formulaire, même si celui-ci a déjà été personnalisé de façon importante par les utilisateurs. Les utilisateurs s'attendent à ce que leurs personnalisations soient conservées après la mise à niveau de la version.
Fournissez un nom unique pour chaque contrôle du formulaire afin de permettre aux personnalisations d'être appliquées aux contrôles. Les personnalisations de formulaire sont stockées sous la forme d'un ensemble d'actions ciblant un contrôle spécifique ou un ensemble de contrôles. Le contrôle cible est référencé par nom, c’est pourquoi il est important de conserver les noms de contrôle entre les versions du formulaire. Si un contrôle n’a pas de nom, l’Éditeur de personnalisation de formulaire génère un nom, mais le nom généré n’est pas conservé dans différentes versions du formulaire.
Assurez-vous que les noms de contrôle restent immuables dans différentes versions du formulaire. Cela permet de conserver les personnalisations apportées à un contrôle dans la version suivante du formulaire.
Si possible, évitez de déplacer les contrôles vers un autre emplacement du même onglet lors de la mise à niveau du formulaire. L'une des personnalisations fréquemment apportées par les utilisateurs est le déplacement des contrôles du formulaire vers un autre emplacement. Si vous modifiez l’emplacement d’un contrôle dans une nouvelle version du formulaire, il existe un risque que le nouvel emplacement du contrôle puisse chevaucher un contrôle que l’utilisateur a déplacé.
Si possible, évitez de déplacer des contrôles entre les onglets lorsque vous concevez une mise à jour vers un formulaire existant. Les contrôles sont identifiés à la fois par nom et par l’onglet sur lequel ils se trouvent. Le déplacement d'un contrôle d'un onglet à l'autre dans le cadre d'une nouvelle version peut annuler les personnalisations apportées par les utilisateurs au contrôle en question, car elles ne pourront pas identifier le contrôle cible.
Lorsque la mise à jour d’un formulaire inclut de nouveaux contrôles, envisagez d’ajouter les nouveaux contrôles à un nouvel onglet. Il s’agit du moyen le plus sûr d’éviter d’interférer avec les personnalisations utilisateur sur les onglets et contrôles existants.
N'oubliez pas la façon dont les contrôles doivent être liés. Les contrôles en lecture seule doivent utiliser uniquement des liaisons unidirectionnelles.
Nommer tous les contrôles personnalisables
Assurez-vous que le nom des contrôles reflète les données auxquelles ils sont liés, ou bien le rôle qu'ils jouent.
Lier le formulaire aux sources de données
L’objectif principal d’un formulaire est de visualiser un objet unique à partir de la base de données Service Manager. Cet objet est une target instance, qui est toujours spécifiée par la propriété DataContext d'un formulaire (héritée de la classe FrameworkElement ).
Important
Ne modifiez pas la propriété DataContext du formulaire. L'environnement d'hébergement des formulaires utilise cette propriété pour identifier l'instance cible du formulaire.
Dans le modèle de données Service Manager, une instance cible est représentée en tant qu’objet BindableDataItem . Cette classe agrège l'objet de Kit de développement logiciel (SDK) sous-jacent, puis expose ses propriétés via un indexeur acceptant un nom de propriété en tant que paramètre.
La classe BindableDataItem implémente également ICustomTypeDescriptor, ce qui permet l'utilisation de la classe BindableDataItem en tant que source de données pour la liaison WPF. L'exemple suivant illustre la liaison d'une propriété d'instance cible à la propriété Text du contrôle TextBox :
<TextBox Name="textBoxDescription" Text="{Binding Path=Summary}"/>
Il n’est pas nécessaire de spécifier la source de la liaison, car les instances cibles sont définies comme DataContext du formulaire, qui sert de source par défaut pour tous les contrôles du formulaire.
Les contrôles du formulaire peuvent être liés à des sources de données autres que l’instance cible, et la bibliothèque d’infrastructure de formulaires contient de nombreux contrôles qui effectuent implicitement la liaison. Par exemple, le contrôle de sélecteur d'instance est lié à la source de données, qui fournit la collection d'instances à sélectionner. Il est également possible de définir des sources de données supplémentaires de manière déclarative à l’aide des classes ObjectDataProvider et XmlDataProvider .
L'infrastructure des formulaires considère l'instance cible comme la seule source de données en lecture-écriture du formulaire. Par conséquent, l'implémentation de la commande Submit stocke uniquement les modifications apportées à l'instance cible. Les autres sources de données du formulaire sont en lecture seule.
Utiliser les règles de validation d’infrastructure de Service Manager, les converteurs de valeur et les modèles d’erreur
Nous vous recommandons d’utiliser des règles de validation d’infrastructure de formulaires dans des formulaires pour désigner l’entrée de données qui n’est pas valide. L'infrastructure de liaison WPF prend en charge la validation des propriétés de contrôle qui sont liées à une source de données par le biais de liaisons unidirectionnelles ou bidirectionnelles. L'objet de liaison est associé à une collection de ValidationRule pouvant contenir tout nombre d'objets ValidationRule . À chaque insertion des données du contrôle dans la source de données, les objets ValidationRule sont appelés pour valider la valeur.
La bibliothèque d’infrastructure de formulaires contient de nombreuses règles de validation qui gèrent les cas les plus courants. L'infrastructure des formulaires s'appuie sur les règles de validation pour déterminer si le contenu du formulaire peut être envoyé en vue de son stockage. Par exemple, le bouton Envoyer d’un formulaire peut être désactivé s’il existe un contrôle qui a une erreur de validation sur le formulaire.
Il est recommandé d'utiliser le modèle d'erreur personnalisé qui est fourni avec la bibliothèque d'infrastructure des formulaires. En cas d'erreur de validation d'un contrôle, celui-ci apparaît par défaut avec une bordure rouge. WPF permet de définir un indicateur d'erreur personnalisé par le biais de la propriété Validation.ErrorTemplate , qui peut être définie pour n'importe quel contrôle. La bibliothèque d’infrastructure de formulaires Service Manager contient un modèle d’erreur personnalisé, qui affiche une icône d’erreur au lieu de la bordure rouge WPF. En outre, lorsque l'utilisateur pointe sur l'icône d'erreur à l'aide de la souris, une info-bulle apparaît avec un message d'erreur. Le message d'erreur doit indiquer la raison de l'échec de la validation des données du contrôle.
L'exemple suivant indique comment référencer le modèle d'erreur dans le code XAML :
<TextBox Text="{Binding SomeProperty}"
scwpf:Validation.ValueRequired="True"
Validation.ErrorTemplate="{DynamicResource {ComponentResourceKey {x:Type scwpf:Validation}, InvalidDataErrorTemplate}}"/>
Si les règles de validation intégrées ne fournissent pas la logique de validation requise, nous vous recommandons de créer des règles de validation personnalisées pour représenter cette logique. Cela permet la coexistence des logiques de validation standard et personnalisée au sein du mécanisme commun de gestion des validations.
Si le mécanisme de règles de validation n’est pas approprié pour un scénario particulier, vous devez à la place gérer FormEvents.PreviewSubmitEvent et exécuter la validation à partir de là.
L'exemple de code suivant fournit un exemple du modèle que vous pouvez utiliser pour exécuter une validation personnalisée :
void MyForm_Loaded(object sender, RoutedEventArgs e)
{
// hook to handle form events
this.AddHandler(
FormEvents.PreviewSubmitEvent,
new EventHandler<PreviewFormCommandEventArgs>(this.OnPreviewSubmit));
}
private void OnPreviewSubmit(object sender, PreviewFormCommandEventArgs e)
{
string errorMessage;
bool result = this.DoVerify(out errorMessage);
if (!result)
{
// cancel Submit operation
e.Cancel = true;
// display error message
MessageBox.Show(errorMessage);
}
}
internal bool DoVerify(out string errorMessage)
{
// Do custom verification and return true to indicate that
// validation check has passed; otherwise return false and
// populate errorMessage argument
}
Utiliser des commandes et des événements d’infrastructure de formulaire
L’infrastructure de formulaire expose de nombreuses commandes qui peuvent être exécutées sur un formulaire. Ces commandes sont les suivantes :
FormsCommand.Submit, qui enregistre l'instance cible du formulaire.
FormsCommand.SubmitAndClose, qui enregistre l'instance cible du formulaire, puis ferme le formulaire.
FormsCommand.Refresh, qui répète la requête pour l'instance cible du formulaire.
FormCommands.Cancel, qui ignore toutes les modifications et ferme le formulaire.
Chacune de ces commandes est encadrée par des événements, qui sont déclenchés avant et après l'exécution de la commande.
Les événements suivants sont déclenchés avant la commande :
L'événement FormEvents.PreviewSubmit est déclenché avant la commande FormCommand.Submit , et l'événement FormEvents.Submitted est déclenché après la commande FormCommand.Submit .
L'événement FormEvents.PreviewRefresh est déclenché avant la commande FormCommands.Refresh , et la commande FormCommand.Refreshed est déclenchée après la commande FormCommand.Submit .
L'événement FormEvents.PreviewCancel est déclenché avant la commande FormCommands.Cancel , et l'événement FormCommand.Canceled est déclenché après la commande FormCommand.Cancel .
Les événements d'aperçu passent un objet PreviewFormCommandEventArgs . Cet objet contient une propriété Cancel mutable qui empêchera l'exécution de la commande correspondante lorsque la propriété est définie sur true.
Les événements post-commande passent un objet FormCommandExecutedEventArgs . Cet objet contient une propriété Result qui indique si l'exécution de la commande a réussi, a été annulée ou a provoqué une erreur. En cas d'erreur, la propriété Error de l'objet FormCommandExecutedEventArgs référence l'exception qui fournit les informations relatives à l'erreur.
Il est possible d’activer, désactiver et exécuter des commandes de formulaire par programmation et de manière déclarative.
Pour activer les commandes de formulaire par programme, établissez une liaison CommandBinding entre le formulaire et la commande.
Dans l'exemple suivant, une liaison de commande est établie entre le formulaire et une commande Refresh , et deux gestionnaires sont définis pour cette commande. Le premier gestionnaire indique si une commande Refresh peut être exécutée. Le second gestionnaire contient l'implémentation de la commande Refresh :
public class MyForm : UserControl
{
public MyForm()
{
// do standard initialization
// establish CommandBinding for Refresh command
this.CommandBindings.Add(
new CommandBinding(FormCommands.Refresh, this.ExecuteRefresh, this.CanExecuteRefresh));
}
private void CanExecuteRefresh(
object sender,
CanExecuteRoutedEventArgs e)
{
// put your logic that determines whether Refresh
// can be executed here
bool canExecute = true;
BindableDataItem dataItem = this.DataContext as BindableDataItem;
if (dataItem)
{
canExecute = dataItem["Status"] != "New";
}
e.CanExecute = canExecute;
}
private void ExecuteRefresh(
object sender,
ExecutedRoutedEventArgs e)
{
// here is placeholder for the code that has do be
// executed upon running Refresh command
}
}
Vous pouvez également définir des gestionnaires pour les commandes de formulaire de manière déclarative. Pour cela, utilisez un objet Rule qui utilise un RoutedCommandTrigger. L'exemple de code suivant montre comment définir des gestionnaires de façon déclarative :
<scwpf:BusinessLogic.Rules>
<scwpf:RuleCollection>
<scwpf:Rule>
<scwpf:Rule.Triggers>
<scwpf:RoutedCommandTrigger
RoutedCommand="{x:Static scwpf:FormCommands.Refresh}"/>
</scwpf:Rule.Triggers>
<scwpf:Rule.Conditions>
<scwpf:PropertyMatchCondition
Binding="{Binding Status}"
Value="New"
Operation="NotEquals" />
</scwpf:Rule.Conditions>
<!-- Use RuleAction objects to define the logic that executed
upon running Refresh command; this can be left empty -->
</scwpf:Rule>
</scwpf:RuleCollection>
</scwpf:BusinessLogic.Rules>
Étapes suivantes
- Personnalisez et créez des formulaires avec l’outil de création Service Manager.
- Personnalisez le formulaire d’incident par défaut pour l’exemple de scénario de l’outil de création.