web-dev-qa-db-fra.com

Comment éviter une exception "référence d'objet non définie sur une instance d'un objet" dans le code XAML lors de la conception?

J'ai un problème avec un contrôle utilisateur wpf qui est de ma propre conception. Le problème est que j'obtiens un object reference not set to an instance of an object exception dans le code XAML lors de la conception, lorsque j'implémente le contrôle utilisateur dans mon programme.

Comment puis-je corriger ou supprimer l'exemption?

EDIT 1

Le designer me montre les informations suivantes:

à Microsoft.Expression.Platform.InstanceBuilders.InstanceBuilderOperations.InstantiateType (Type type, Boolean supportInternal) à Microsoft.Expression.Platform.InstanceBuilders.ClrObjectInstanceBuilder.InstantiateTargetType (IInstanceBuilderContext context, ViewNode viewInodeBusInuClientInstanceBuilder (Contexte IInstanceBuilderContext, ViewNode viewNode) sur Microsoft.Expression.WpfPlatform.InstanceBuilders.FrameworkElementInstanceBuilder.Instantiate (IInstanceBuilderContext context, ViewNode viewNode) sur Microsoft.Expression.WpfPlatform.InstanceBuilders.UsContext Platform.InstanceBuilders.ViewNodeManager.CreateInstance (générateur IInstanceBuilder, ViewNode viewNode)

Je pense qu'ils ne sont pas vraiment utiles ...

15
Kimbo

Si la référence d'objet n'est pas définie sur une instance d'un objet dans XAML, mais que votre application se compile et s'exécute correctement, vous découvrirez généralement que sa cause est quelque chose dans un constructeur qui ne peut pas être résolu au moment du design.

Vous pouvez simplement cliquer sur le bouton "Désactiver le code de projet" situé en bas de votre vue de concepteur et le concepteur Visual Studio cessera d'essayer de construire une instance pour fournir une vue des données au moment de la conception.

Voir ici pour des informations détaillées et des captures d'écran.

18
Lirrik

Tout ce qui se passe dans votre constructeur lève une exception pendant la conception. J'ai eu le même problème - je viens de mettre un crochet autour du code problématique - dans mon cas, j'appelais ServiceLocator.Current car j'utilise un conteneur IoC. Mais il n'y a pas de conteneur pendant la conception. J'ai donc enveloppé dans un catch catch pour supprimer l'erreur et cela a fonctionné. Pas la meilleure solution ... mais c'est une solution.

5
Shumii

J'ai tendance à utiliser la classe LicenseManager dans System.ComponentModel pour éviter que mes ViewModels ne génèrent des erreurs désagréables au moment du design. Par exemple:

public MyViewModel()
{
  if (LicenseManager.UsageMode == LicenseUsageMode.Runtime)
  {
    // Do runtime stuff
  }
}
3
Gareth

En ajustant l'exemple de BobHorn, j'ai obtenu que cela fonctionne pour moi:

public class ViewModel
{
    public ViewModel()
    {
        if (!IsInDesignMode)
        {
            //Constructor code here...
        }
    }
    public bool IsInDesignMode
    {
        get
        {
            var prop = DesignerProperties.IsInDesignModeProperty;
            return (bool)DependencyPropertyDescriptor
                .FromProperty(prop, typeof(FrameworkElement))
                .Metadata.DefaultValue;
        }
    }
}

Bien qu'utilisant sa suggestion exacte pour le constructeur

public Main()
{
    if (IsInDesignMode) { return; }
    //Constructor code here...
}

A également fonctionné pour moi, je préfère juste ne pas court-circuiter mes méthodes avec des déclarations de retour supplémentaires. J'aurais voté pour sa réponse, je n'ai pas encore le représentant.

2
aherocalledFrog

J'ai eu le même problème. Il vous suffit de vous rendre dans Outils> Options> XAML Designer et d'activer l'option

"Exécuter le code du projet dans le concepteur XAML".

Redémarrez enfin Visual Studio. J'espère que cela vous aidera.

1
Dark Knight

Vous pouvez faire quelque chose comme ça:

using System.ComponentModel;
using System.Windows;

/// <summary>
/// WPF Design Mode helper class.
/// </summary>
public static class DesignMode
{
    private static bool? _isInDesignMode;

    /// <summary>
    /// Gets a value indicating whether the control is in design mode (running in Blend
    /// or Visual Studio).
    /// </summary>
    public static bool IsInDesignMode
    {
        get
        {
            if (!_isInDesignMode.HasValue)
            {
                var prop = DesignerProperties.IsInDesignModeProperty;
                _isInDesignMode
                    = (bool)DependencyPropertyDescriptor
                    .FromProperty(prop, typeof(FrameworkElement))
                    .Metadata.DefaultValue;
            }

            return _isInDesignMode.Value;
        }
    }
}

Ensuite, en tant que première ligne du constructeur de votre vue (ou modèle de vue), vous pouvez faire quelque chose comme ceci:

if (DesignMode.IsInDesignMode) { return; }

De cette façon, votre code ne s'exécutera que lorsque vous l'exécuterez réellement.

1
Bob Horn

Lorsque vous travaillez sur un WIndow/UserControl dans le concepteur, il "exécute" le constructeur sans paramètre. Si vous avez du code qui dépend de quelque chose habituellement fourni par un autre morceau de code, cela cause souvent un problème. Le concepteur n'exécute pas d'autre code en premier, donc les dépendances généralement fournies ailleurs peuvent être manquantes et provoquer des erreurs. Leur suppression consiste à détecter si ce code s'exécute dans le concepteur ou non. Il est souvent plus pratique de simplement retourner le constructeur:

public MainWindow()
{
    InitializeComponent();
    if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
        return;

    //code
}

Plus en détail https://social.technet.Microsoft.com/wiki/contents/articles/29874.aspx?Redirected=true

0
Raj

Si quelqu'un d'autre vient ici, j'ai glissé par inadvertance mon fichier MainWindow.xaml dans un sous-dossier. Le faire glisser vers l'arrière a résolu le problème.

0
Alan

Remplacez l'option "Build only" par "Intellisense only" dans la fenêtre de la liste des erreurs

0
Yerla

Dans votre "classe partielle" de XAML, si vous pouvez voir "[XamlCompilation(XamlCompilationOptions.Compile)]", supprimez simplement la ligne, puis réessayez de construire.

0
Jagger

VS 2017 UWP:

if (false == Windows.ApplicationModel.DesignMode.DesignModeEnabled)
{
     // Anything in here need not be OK at Design time in Visual Studio                 
}
0
Paulustrious