Partager via


Dépannage des erreurs de chargement des concepteurs WPF et Silverlight

Le Concepteur WPF pour Visual Studio intègre un concepteur visuel sophistiqué et extensible qui restitue le code XAML. Si votre fichier XAML ne se charge pas dans le concepteur, vous pouvez effectuer plusieurs actions permettant de déterminer le problème. Cette rubrique fournit quelques conseils et techniques permettant de résoudre les problèmes de chargement du Concepteur WPF. Les exemples de cette rubrique se concentrent sur le WPF, mais la plupart des problèmes, techniques et solutions sont applicables au WPF et à Silverlight.

Notes

De nombreuses techniques présentées dans cette rubrique s'appliquent également à Expression Blend.

Débogage d'un échec de chargement

Utilisez le débogueur Visual Studio pour effectuer un pas à pas détaillé dans votre code au moment du design. Vous pouvez utiliser une deuxième instance de Visual Studio pour déboguer les échecs de chargement. Pour plus d'informations, consultez Comment : déboguer une erreur de chargement de concepteur.

Étapes de dépannage

Les étapes suivantes permettent de résoudre les problèmes de chargement du Concepteur WPF.

  1. Lisez tous les messages d'exception qui s'affichent.

    Cette étape peut paraître évidente, mais si vous recevez une exception, lisez clairement le message. Dans certains cas, il permet de diagnostiquer rapidement le problème. Pour plus d'informations, consultez Débogage et interprétation d'erreurs dans le Concepteur WPF.

  2. Déterminez si le problème est lié à votre implémentation.

    Générez et exécutez votre application pour déterminer si le problème est uniquement le résultat de votre implémentation ou une interaction avec le Concepteur WPF. Si l'application se génère et s'exécute, l'erreur au moment du design est vraisemblablement provoquée par votre implémentation.

  3. Déterminez si le problème est une erreur de chargement.

    En cas d'échec du chargement du mode Design suite à une exception, le problème est probablement une erreur de chargement. Si vous disposez de code personnalisé chargé au moment du design et que vous rencontrez des exceptions ou des échecs de chargement au moment du design, consultez la section Écriture de code pour le moment de design dans cette rubrique.

  4. Examinez le code chargé au moment du design.

    Il existe deux approches liées à l'écriture de code qui s'exécute également au moment du design. La première approche consiste à écrire du code défensif en vérifiant les paramètres d'entrée pour les classes. La seconde approche consiste à vérifier si le mode Design est actif en appelant la méthode GetIsInDesignMode. Pour plus d'informations, consultez la section Écriture de code pour le moment de design dans cette rubrique.

  5. Examinez les autres zones de votre code.

    Consultez la section Conseils de programmation de cette rubrique pour obtenir des conseils de programmation lorsque vous utilisez Concepteur WPF. Consultez la section Meilleures pratiques de programmation de cette rubrique pour connaître les techniques permettant d'écrire du code plus fiable.

  6. Si les problèmes persistent, vous pouvez utiliser le forum de WPF Designer sur MSDN pour communiquer avec d'autres développeurs qui utilisent Concepteur WPF. Pour signaler des problèmes potentiels ou envoyer des suggestions, utilisez le site Commentaires sur Visual Studio et le .NET Framework.

Écriture de code pour le moment de design

Assurez-vous que votre code s'exécute au moment du design et au moment de l'exécution. Si votre code s'exécute au moment du design, ne supposez pas que Application.Current correspond à votre application. Par exemple, lorsque vous utilisez Expression Blend, Current correspond à Expression Blend. Au moment du design, MainWindow n'est pas la fenêtre principale de votre application. Les opérations courantes qui provoquent l'échec d'un contrôle personnalisé au moment du design sont, entre autres, les suivantes.

Il existe deux approches liées à l'écriture de code pour le moment du design. La première approche consiste à écrire du code défensif en vérifiant les paramètres d'entrée pour les classes (convertisseurs de valeur, par exemple). La seconde approche consiste à vérifier si le mode Design est actif en appelant la méthode GetIsInDesignMode. Pour Silverlight, utilisez la propriété IsInDesignTool.

Il est nécessaire de vérifier les paramètres d'entrée de certaines implémentations, car l'environnement de design fournit, pour certaines entrées, d'autres types que ceux fournis par l'environnement d'exécution.

En règle générale, les sélecteurs de style et les convertisseurs de valeur nécessitent l'une de ces approches pour pouvoir s'exécuter correctement au moment du design.

Convertisseurs de valeur

Vos implémentations IValueConverter personnalisées doivent vérifier la présence de la valeur null et du type attendu dans le premier paramètre de la méthode Convert. Le code XAML suivant montre une liaison vers Application.Current qui échoue au moment du design si le convertisseur de valeur n'est pas correctement implémenté.

<ComboBox.IsEnabled>
    <MultiBinding Converter="{StaticResource specialFeaturesConverter}">
        <Binding Path="CurrentUser.Rating" Source="{x:Static Application.Current}"/>
        <Binding Path="CurrentUser.MemberSince" Source="{x:Static Application.Current}"/>
    </MultiBinding>
</ComboBox.IsEnabled>

La liaison lève une exception au moment du design, car Application.Current fait référence à l'application de concepteur au lieu de votre application. Pour éviter l'exception, le convertisseur de valeur doit vérifier ses paramètres d'entrée ou vérifier le mode Design.

L'exemple de code suivant indique comment vérifier des paramètres d'entrée dans un convertisseur de valeur qui retourne la valeur true si deux paramètres d'entrée répondent à une logique métier particulière.

public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    // Check the values array for correct parameters.
    // Designers may send null or unexpected values.
    if (values == null || values.Length < 2) return false;
    if (!(values[0] is int)) return false;
    if (!(values[1] is DateTime)) return false;

    int rating = (int)values[0];
    DateTime date = (DateTime)values[1];

    // If the user has a good rating (10+) and has been a member for 
    // more than a year, special features are available.
    if((rating >= 10) && 
        (date.Date < (DateTime.Now.Date - new TimeSpan(365, 0, 0, 0))))
    {
        return true;
    }
    return false;
}

La seconde approche à suivre pour écrire du code pour le moment du design consiste à vérifier si le mode Design est actif. L'exemple de code suivant affiche une vérification du mode Design au lieu de la vérification de paramètres illustrée précédemment.

public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    // Check for design mode. 
    if ((bool)(DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof(DependencyObject)).DefaultValue)) 
    {
        return false;
    }

    int rating = (int)values[0];
    DateTime date = (DateTime)values[1];

    // If the user has a good rating (10+) and has been a member for 
    // more than a year, special features are available.
    if((rating >= 10) && 
        (date.Date < (DateTime.Now.Date - new TimeSpan(365, 0, 0, 0))))
    {
        return true;
    }
    return false;
}

Sélecteurs de style

Vos sélecteurs de style personnalisés doivent également être implémentés pour s'exécuter en mode Design. Le code XAML suivant affiche un sélecteur de modèle personnalisé qui utilise Application.MainWindow au moment de l'exécution afin de déterminer la ressource retournée en tant que DataTemplate. Au moment du design, cette ressource risque de ne pas être disponible ; dès lors, la substitution SelectTemplate retourne null au moment du design.

<local:TaskListDataTemplateSelector x:Key="myDataTemplateSelector"/>
<ListBox Width="400" Margin="10"
    ItemsSource="{Binding Source={StaticResource myTodoList}}"
    ItemTemplateSelector="{StaticResource myDataTemplateSelector}"
    HorizontalContentAlignment="Stretch" 
    IsSynchronizedWithCurrentItem="True"/>

Le code suivant montre l'implémentation du sélecteur de style.

public class TaskListDataTemplateSelector : DataTemplateSelector
{
    public override DataTemplate SelectTemplate(
        object item, 
        DependencyObject container)
    {
        if (item != null && item is Task)
        {
            Task taskitem = item as Task;
            Window window = Application.Current.MainWindow;

            // To run in design mode, either test for the correct window class
            // or test for design mode.
            if (window.GetType() == typeof(MainWindow))
            // Or check for design mode: 
            //if (!DesignerProperties.GetIsInDesignMode(window))
            {
                if (taskitem.Priority == 1)
                return window.FindResource("importantTaskTemplate") as DataTemplate;
                else
                return window.FindResource("myTaskTemplate") as DataTemplate;
            }
        }
        return null;
    }
}

Conseils de programmation

Vous trouverez ci-dessous quelques conseils de programmation à suivre lorsque vous utilisez le Concepteur WPF.

Meilleures pratiques de programmation

Vous trouverez ci-dessous quelques-unes des meilleures pratiques de programmation permettant d'écrire du code plus fiable pour le Concepteur WPF.

  • Encapsulez toujours les portées d'édition dans des instructions using ou dans des blocs try/finally. Si une exception est levée, la modification est abandonnée dans l'appel Dispose. Pour plus d'informations, consultez ModelEditingScope.

  • Utilisez ModelEditingScope pour déplacer un contrôle d'un conteneur à un autre. Une exception est levée en cas d'échec du déplacement.

  • Dans WPF et le Concepteur WPF, n'utilisez pas de valeur de propriété par défaut si vous avez l'intention de l'effacer. Pour les valeurs NaN, comme Height, appelez la méthode ClearValue au lieu d'assigner NaN.

  • Lorsque vous récupérez des valeurs d'une propriété, utilisez la valeur calculée de la propriété. Vous devez dès lors utiliser la propriété ComputedValue au lieu de la méthode GetCurrentValue de ModelItem. La méthode GetCurrentValue retourne des liaisons et d'autres expressions si elles sont stockées dans le code XAML. Dans certains cas, vous pouvez dès lors obtenir des exceptions de cast.

Voir aussi

Concepts

Gestion des exceptions (débogage)

Autres ressources

Comment : déboguer une erreur de chargement de concepteur

Débogage et interprétation d'erreurs dans le Concepteur WPF

Procédures pas à pas pour XAML et le code