Comment détecter les bris de liaison de données WPF?

en essayant de répondre à une question dans les environs " Unit Testing WPF Bindings " j'ai eu la question suivante..

" Quelle est la meilleure façon de trouver si vous avez le câblage de liaison de données WPF mal configuré (ou si vous venez de casser quelque chose qui a été câblé correctement) ?

bien que L'approche de test de l'unité semble être comme celle de Joel "arracher votre bras pour enlever une écharde".. Je suis à la recherche autour pour plus facile moins de moyens aériens pour détecter cela.

tout le monde semble s'être engagé à lier les données de manière importante avec WPF.. et il a ses mérites.

68
demandé sur Community 2008-12-03 16:04:22

7 réponses

dans .NET 3.5 il a été introduit une nouvelle façon de produire spécifiquement des informations de traçage sur des reliures de données spécifiques.



Cela se fait à travers le nouveau système .Diagnostic.PresentationTraceSources.TraceLevel bien attaché que vous pouvez appliquer à toute liaison ou fournisseur de données. Voici un exemple:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
    Title="Debug Binding Sample"
    Height="300"
    Width="300">
    <StackPanel>
        <TextBox Name="txtInput" />
        <Label>
            <Label.Content>
                <Binding ElementName="txtInput"
                         Path="Text"
                         diag:PresentationTraceSources.TraceLevel="High" />
            </Label.Content>
        </Label>
    </StackPanel>
</Window>

cela mettra des informations de trace pour juste que la fixation particulière dans le visuel La fenêtre de sortie de Studio, sans aucune configuration de traçage nécessaire.

65
répondu Enrico Campidoglio 2008-12-05 08:35:39

du Mieux que j'ai pu trouver...

Comment puis-je déboguer les consolidations WPF? par Beatriz Stollnitz

puisque tout le monde ne peut pas toujours garder un oeil sur la fenêtre de sortie à la recherche d'erreurs de liaison, j'ai adoré L'Option#2. Qui est d'ajouter ceci à votre application.Config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.diagnostics>
    <sources>
      <source name="System.Windows.Data" switchName="SourceSwitch" >
        <listeners>
          <add name="textListener" />
        </listeners>
      </source>

    </sources>
      <switches>
        <add name="SourceSwitch" value="All" />
      </switches>

      <sharedListeners>
        <add name="textListener"
        type="System.Diagnostics.TextWriterTraceListener"
        initializeData="GraveOfBindErrors.txt" />
      </sharedListeners>

      <trace autoflush="true" indentsize="4"></trace>

  </system.diagnostics>
</configuration>

jumelez cela avec un bon script de scan regex pour extraire les informations pertinentes, que vous pouvez exécuter de temps en temps sur les GraveOfBindErrors.txt dans votre dossier de sortie

System.Windows.Data Error: 35 : BindingExpression path error: 'MyProperty' property not found on 'object' ''MyWindow' (Name='')'. BindingExpression:Path=MyProperty; DataItem='MyWindow' (Name=''); target element is 'TextBox' (Name='txtValue2'); target property is 'Text' (type 'String')
38
répondu Gishu 2016-11-06 20:17:20

vous pouvez utiliser la fonction de débogage de déclenchement de WPF Inspector. Il suffit de télécharger l'outil de codeplex et le joindre à votre application en cours d'exécution. Il affiche également les erreurs de liaison sur le bas de la fenêtre. Outil très utile!

enter image description here

5
répondu Christian Moser 2018-05-28 14:23:40

j'utilise la solution présentée ici pour transformer les erreurs de liaison en Exceptions natives: http://www.jasonbock.net/jb/Default.aspx?blog=entry.0f221e047de740ee90722b248933a28d

cependant, un scénario normal dans les consolidations WPF est de jeter des exceptions dans le cas où l'utilisateur ne peut pas être converti au type cible (par exemple, une boîte de texte liée à un champ entier; l'entrée d'une chaîne non-numérique résulte en une FormatException, l'entrée de nombre c'est trop de résultats dans un Ovflowexception). Un cas similaire est lorsque le Setter de la propriété source lance une exception.

la façon de traiter ceci est via ValidatesOnExceptions=true et ValidationExceptionRule pour signaler à l'utilisateur que l'entrée fournie n'est pas correcte (en utilisant le message d'exception).

cependant, ces exceptions sont également envoyées à la fenêtre de sortie et donc "capturées" par le BindingListener, ce qui entraîne une erreur...clairement pas le comportement que vous voulez.

par conséquent, j'ai élargi la classe BindingListener pour ne pas jeter une Exception dans ces cas:

private static readonly IList<string> m_MessagesToIgnore =
        new List<String>()
        {
            //Windows.Data.Error 7
            //Binding transfer from target to source failed because of an exception
            //Normal WPF Scenario, requires ValidatesOnExceptions / ExceptionValidationRule
            //To cope with these kind of errors
            "ConvertBack cannot convert value",

            //Windows.Data.Error 8
            //Binding transfer from target to source failed because of an exception
            //Normal WPF Scenario, requires ValidatesOnExceptions / ExceptionValidationRule
            //To cope with these kind of errors
            "Cannot save value from target back to source"  
        };

lignes modifiées dans public override void WriteLine (string message) :

        ....
        if (this.InformationPropertyCount == 0)
        {
            //Only treat message as an exception if it is not to be ignored
            if (!m_MessagesToIgnore.Any(
                x => this.Message.StartsWith(x, StringComparison.InvariantCultureIgnoreCase)))
            {
                PresentationTraceSources.DataBindingSource.Listeners.Remove(this);

                throw new BindingException(this.Message,
                    new BindingExceptionInformation(this.Callstack,
                        System.DateTime.Parse(this.DateTime),
                        this.LogicalOperationStack, int.Parse(this.ProcessId),
                        int.Parse(this.ThreadId), long.Parse(this.Timestamp)));
            }
            else
            {
                //Ignore message, reset values
                this.IsFirstWrite = true;
                this.DetermineInformationPropertyCount();
            }
        }
    }
4
répondu Jeroen de Bekker 2012-07-24 13:41:30

Voici une technique utile pour déboguer/tracer les déclencheurs efficacement. Il vous permet d'enregistrer toutes les actions de déclenchement ainsi que l'élément sur lequel vous agissez:

http://www.wpfmentor.com/2009/01/how-to-debug-triggers-using-trigger.html

2
répondu 2009-01-23 10:12:42

cela nous a été très utile, mais je voulais ajouter à ceux qui trouvent cela utile qu'il existe un utilitaire que Microsoft fournit avec le sdk pour lire ce fichier.

Trouvés ici: http://msdn.microsoft.com/en-us/library/ms732023.aspx

Pour ouvrir un fichier de trace

1.Démarrez le lecteur de Trace de Service en utilisant une fenêtre de commande pour naviguer vers votre Emplacement de l'installation de la WCF (C:\Program Files\Microsoft SDKs\Windows\v6.0 \ Bin), puis tapez SvcTraceViewer.EXE. (bien que nous ayons trouvé le nôtre dans \v7.0 \ Bin)

Note: l'outil de recherche de Service peuvent s'associer avec deux types de fichiers: .svclog and .stvproj. Vous pouvez utiliser deux paramètres en ligne de commande pour enregistrer et désinscrire les extensions de fichier.

/registre: registre de l'association des des extensions de fichier ".svclog" et ".stvproj " avec SvcTraceViewer.EXE

/unregister: annuler l'inscription de l' association d'extensions de fichiers ".svclog" et ".stvproj " avec SvcTraceViewer.exe

1.Lorsque le Service Trace Viewer démarre, cliquez sur Fichier puis pointez pour ouvrir. Accédez à l'emplacement où votre les fichiers de trace sont stockées.

2.Double-cliquez sur le fichier de trace que vous souhaitez ouvrir.

Note: Appuyez sur Maj en cliquant plusieurs fichiers de trace à sélectionner et les ouvrir simultanément. Service Trace Viewer fusionne le contenu de tous les dossiers et présente une vue. Pour exemple, vous pouvez ouvrir les fichiers de trace de le client et le service. C'est utile lorsque vous avez activé message exploitation forestière et propagation de l'activité dans configuration. De cette façon, vous pouvez examiner l'échange de messages entre le client et le service. Vous pouvez également faire glisser plusieurs fichiers dans le visualiseur, ou utiliser l'onglet Projet. Consultez la Gestion de la Projet d'article pour plus de détails.

3.Pour ajouter des fichiers de trace supplémentaires à la collection qui est ouverte, cliquez sur Fichier et puis pointez sur Ajouter. Dans la fenêtre qui s'ouvre, naviguez jusqu'à l'emplacement des fichiers de trace et double-cliquez le fichier que vous souhaitez ajouter.

aussi, comme pour le filtrage du fichier log, nous avons trouvé ce lien extrêmement utile:

http://msdn.microsoft.com/en-us/library/ms751526.aspx

2
répondu ErocM 2011-03-29 15:11:45

pour quelqu'un comme moi qui cherche une façon programmatique pure de permettre tous les tracés WPF à un niveau de Trace donné, voici un morceau de code qui le fait. Pour référence, il est basé sur cet article: sources de suivi dans WPF .

Il ne nécessite pas un changement dans l'application.fichier de configuration, et il n'est pas non plus nécessaire de changer le registre.

C'est comme ça que je l'utilise, dans un endroit de démarrage (Application, etc.):

....
#if DEBUG
    WpfUtilities.SetTracing();
#endif
....

Et voici le code d'utilité (par défaut il envoie tous les Avertissements à L'auditeur de Trace par défaut):

public static void SetTracing()
{
    SetTracing(SourceLevels.Warning, null);
}

public static void SetTracing(SourceLevels levels, TraceListener listener)
{
    if (listener == null)
    {
        listener = new DefaultTraceListener();
    }

    // enable WPF tracing
    PresentationTraceSources.Refresh();

    // enable all WPF Trace sources (change this if you only want DataBindingSource)
    foreach (PropertyInfo pi in typeof(PresentationTraceSources).GetProperties(BindingFlags.Static | BindingFlags.Public))
    {
        if (typeof(TraceSource).IsAssignableFrom(pi.PropertyType))
        {
            TraceSource ts = (TraceSource)pi.GetValue(null, null);
            ts.Listeners.Add(listener);
            ts.Switch.Level = levels;
        }
    }
}
1
répondu Simon Mourier 2014-05-15 09:40:08