web-dev-qa-db-fra.com

Erreur ReSharper WPF: "Impossible de résoudre le symbole" MyVariable "en raison de DataContext inconnu"

Je rencontre cette erreur lors de l'utilisation de WPF + XAML + MVVM dans Visual Studio 2012.

Impossible de résoudre le symbole "MyVariable" en raison de DataContext inconnu

Quelle est la solution?

31
Contango

Cette erreur est produite par ReSharper lors de la conception de XAML pour WPF et indique que le XAML ne peut pas trouver la classe qui contient des liaisons au moment de l'exécution. Cela indique généralement que DataContext n'est pas défini correctement.

Cette erreur signifie que:

  • Intellisense pour XAML ne fonctionne pas aussi bien au moment de la conception;
  • On ne peut pas naviguer automatiquement du XAML à la classe C # au moment du design en utilisant un Ctrl-Click sur le binding dans le XAML;
  • Lorsque nous sélectionnons "Find Usages" sur une propriété, cela ne fera pas apparaître les usages dans le XAML ainsi que le C #;
  • Le concepteur ne peut pas afficher les données en direct d'une classe C # personnalisée.

Pour ceux d'entre nous qui pensent dans MVVM, cette erreur indique que la vue ne peut pas trouver le ViewModel.

Solution 1

Parcourez une sorte de didacticiel Web pour comprendre le fonctionnement de DataBinding. Recommander Microsoft Data Binding Overview .

Solution 2

Si vous utilisez ReSharper, appuyer sur Alt-Entrée sur le DataContext incriminé fera apparaître un menu qui vous aidera à insérer le DataContext correct dans votre XAML.

J'ai utilisé cela pour résoudre correctement le problème.

enter image description here

Solution 3

Dans le volet "Propriétés" de Visual Studio, vous pouvez sélectionner le contexte de données pour le contrôle sélectionné:

enter image description here

Solution 4

Le mélange peut également être utilisé pour définir le contexte des données. Ouvrez votre fichier .sln dans Blend, sélectionnez l'élément de conception, puis dans les propriétés sélectionnez "Nouveau":

enter image description here

Solution 5

DevExpress peut également vous aider à résoudre cette erreur dans le XAML à l'aide de son assistant.

Dans le XAML, sélectionnez l'élément parent pour lequel vous souhaitez définir le contexte de données (généralement le formulaire entier), puis dans le concepteur, sélectionnez le triangle d'action.

Ensuite, accédez à la classe avec le code C #.

enter image description here

Astuce: La classe sera invisible sauf si vous ajoutez un constructeur sans paramètre à la classe.

XAML avant

<UserControl x:Class="DemoAllocation.MyActualView"
         xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.Microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">

XAML après

<UserControl
         xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.Microsoft.com/expression/blend/2008" 
         xmlns:Implementation="clr-namespace:DemoAllocation.ViewModel.Implementation" x:Class="DemoAllocation.MyActualView" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<UserControl.DataContext>
    <Implementation:MyActualViewModel/>
</UserControl.DataContext>

Indice 6

Si vous ne pouvez pas voir les balises actives sur le concepteur WPF, vérifiez qu’elles n’ont pas été désactivées à un moment donné:

enter image description here

Solution 7

On peut ajouter appeler un extrait de code au démarrage qui apparaît une boîte de message chaque fois qu'il y a une erreur de liaison. Cela s'est avéré très utile.

Dans le cas où le lien Web susmentionné tombe en panne, voici le code:

public partial class Window1 : Window
{
  public Window1()
  {
    BindingErrorTraceListener.SetTrace();
    InitializeComponent();
  }
}

Méthode:

using System.Diagnostics;
using System.Text;
using System.Windows;

namespace SOTC_BindingErrorTracer
{
  public class BindingErrorTraceListener : DefaultTraceListener
  {
    private static BindingErrorTraceListener _Listener;

    public static void SetTrace()
    { SetTrace(SourceLevels.Error, TraceOptions.None); }

    public static void SetTrace(SourceLevels level, TraceOptions options)
    {
      if (_Listener == null)
      {
        _Listener = new BindingErrorTraceListener();
        PresentationTraceSources.DataBindingSource.Listeners.Add(_Listener);
      }

      _Listener.TraceOutputOptions = options;
      PresentationTraceSources.DataBindingSource.Switch.Level = level;
    }

    public static void CloseTrace()
    {
      if (_Listener == null)
      { return; }

      _Listener.Flush();
      _Listener.Close();
      PresentationTraceSources.DataBindingSource.Listeners.Remove(_Listener);
      _Listener = null;
    }



    private StringBuilder _Message = new StringBuilder();

    private BindingErrorTraceListener()
    { }

    public override void Write(string message)
    { _Message.Append(message); }

    public override void WriteLine(string message)
    {
      _Message.Append(message);

      var final = _Message.ToString();
      _Message.Length = 0;

      MessageBox.Show(final, "Binding Error", MessageBoxButton.OK, 
        MessageBoxImage.Error);
    }
  }
}

Solution 8

Utilisez l'utilitaire gratuit Snoop .

Il y a une fonctionnalité vraiment sympa qui vous permet de filtrer par des contrôles avec des erreurs de liaison. Cela vous permet de naviguer directement vers le visuel avec l'erreur de liaison.

Après avoir démarré Snoop:

  1. Cliquez et faites glisser la deuxième icône cible sur votre application en cours d'exécution.
  2. Maintenez la touche Ctrl + Maj enfoncée.
  3. Lorsque vous déplacez votre souris sur l'application en cours d'exécution, le contrôle sous la souris est alors indiqué en rouge.
  4. Relâchez la souris et Snoop fera apparaître une fenêtre qui montre tout le XAML dans l'arborescence visuelle.

enter image description here

enter image description here

Astuce 9 - Contexte des données de conception

Il existe en fait deux DataContexts complètement distincts: design time et run time.

La plupart des solutions précédentes visent à définir le run time DataContext.

Une fois que vous avez défini le design time DataContext, l'aperçu XAML dans Visual Studio ou Blend affichera les données personnalisées fournies par votre classe C # personnalisée.

Si vous utilisez Blend, ces données personnalisées peuvent également être lues à partir d'un fichier XML, mais je préfère les fournir à partir de ma propre classe C #.

Pour définir le design time DataContext, voir:

Ou, ajoutez ceci à n'importe quel élément (cela va créer une nouvelle classe MyClass au moment du design, donc Intellisense fonctionnera):

d:DataContext="{d:DesignInstance d:Type=viewModel:MyClass, IsDesignTimeCreatable=True}"

Et ceci à l'en-tête:

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.Microsoft.com/expression/blend/2008"
mc:Ignorable="d"

Dans les coulisses, lorsque vous définissez le design time DataContext:

  • Le concepteur Visual Studio (ou Blend) instanciera automatiquement une nouvelle instance de la classe vers laquelle vous la dirigez. Cela fonctionne également si vous créez une classe statique.
  • Ensuite, dans l'aperçu XAML, lorsque vous modifiez le XAML, il affichera les données en direct de votre classe C #.
  • Cela rend la conception très rapide, car vous pouvez travailler avec des données en direct au moment de la conception, et vous n'avez pas besoin d'exécuter le programme tout le temps pour voir à quoi il ressemble.

Notez que l'aperçu XAML apparaît uniquement si vous utilisez un contrôle utilisateur. Si vous préférez utiliser des modèles de données, pas de problème: vous pouvez créer un contrôle utilisateur temporaire qui inclut le modèle de données et définir le design time DataContext pour pointer sur une classe statique. Codez la classe statique afin qu'elle crée une nouvelle instance de votre ViewModel (c'est-à-dire la classe à laquelle vous souhaitez vous lier). Par exemple, votre classe statique pourrait lire les données d'une base de données, remplir les propriétés du ViewModel et vous pourriez travailler avec des données en direct de la base de données au moment de la conception XAML.

Cette technique fonctionne également parfaitement avec l'injection de dépendance, comme Unity ou MEF. Vous devez pointer votre design time DataContext à une classe statique qui récupère les classes appropriées du conteneur d'injection de dépendances et configure tout. Vous pouvez ensuite voir les données en direct au moment de la conception dans l'aperçu XAML. Les liens susmentionnés montrent comment cela fonctionne (avec des vidéos YouTube d'une horloge en direct au moment de la conception XAML!).

Inutile de dire que cette technique fonctionne parfaitement avec le modèle MVVM, ainsi qu'avec MVVM + Dependency Injection. Pour ceux d'entre vous qui ne connaissent pas MVVM, c'est un excellent moyen de produire des projets élégants, propres, maintenables et faciles à modifier. Microsoft Blend lui-même est entièrement écrit en utilisant le modèle MVVM.

95
Contango