web-dev-qa-db-fra.com

Existe-t-il un moyen de déterminer où une liaison WPF est déclarée/créée?

J'ai un projet qui génère des erreurs de liaison de données. Un exemple est:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''. BindingExpression:Path=HorizontalContentAlignment; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'HorizontalContentAlignment' (type 'HorizontalAlignment')

Ma question est de savoir s'il existe un moyen de déterminer où cette liaison est réellement déclarée (ou elle est déclarée en XAML ou en code).

Ce que j'ai essayé jusqu'à présent:

  • ajout d'une trace de débogage pour l'espace de noms System.Windows.Data avec le niveau défini o All; cela n'a pas produit plus d'informations utiles
  • essayé de faire une recherche de texte dans le projet pour le mot Binding dans l'espoir de localiser toutes les expressions de liaison dont le chemin est défini sur HorizontalContentAlignmentname__; Je n’en ai trouvé qu’un et l’ai enlevé, mais je reçois toujours le message qui semble indiquer que ce n’était pas le défaut.

Connaissez-vous d'autres astuces pour faire en sorte que WPF publie des informations plus utiles sur l'emplacement exact où cette liaison est déclarée?

METTRE À JOUR

Après un peu plus de recherches, je suis presque certain que cela est dû à un style appliqué à un MenuItemname__. Cependant, je ne suis toujours pas en mesure de localiser l'emplacement où la liaison défectueuse est déclarée.

UPDATE 2

J'ai trouvé le problème. Cependant, la question demeure, car trouver le problème consistait principalement à effectuer une recherche dans le noir sur la base des informations limitées contenues dans le message d'erreur.

Il s'avère que la liaison est déclarée dans un style. Et le style n'est pas dans mon application. C'est probablement le style par défaut pour MenuItemname__. Donc, pour résoudre le problème pour le moment, je viens de définir manuellement le HorizontalContentAlignmentsur tous les MenuItemsname__. La raison de l'erreur est liée à l'ordre des opérations car ce MenuItemest généré dans le code. Je posterai une nouvelle question à ce sujet séparément.

Donc, pour l’instant, la morale de l’histoire est que j’estime qu’il faut un meilleur mécanisme pour déterminer où la reliure défectueuse est déclarée. Je voudrais voir quelque chose comme une trace de pile pour les liaisons ..

Je laisse la question ouverte un peu plus longtemps au cas où quelqu'un aurait connaissance d'autres outils ou méthodes permettant de déterminer le lieu où une liaison est déclarée dans le code ou le balisage.

J'ai posté une autre question concernant le style/la liaison appliquée à MenuItemshere .

29
Mike Dinescu

Lors du débogage des erreurs de liaison WPF, il est plus facile de séparer l'erreur par des points-virgules et de commencer à la fin.

  1. System.Windows.Data Error: 4 :
  2. Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''. BindingExpression:Path=HorizontalContentAlignment;
  3. DataItem=null;
  4. target element is 'MenuItem' (Name='');
  5. target property is 'HorizontalContentAlignment' (type 'HorizontalAlignment')

Donc à partir de la fin:

  • N ° 5 vous indique quelle propriété contient la liaison qui échoue. Dans votre cas, c'est HorizontalContentAlignment

  • # 4 est l'élément contenant la propriété en échec, qui est une MenuItem sans une Name pour l'identifier par

    Donc, quelque part, vous avez un <MenuItem HorizontalContentAlignment="{Binding ...}" /> qui est à l'origine de l'erreur de liaison.

  • # 3 est la DataItem ou DataContext qui se trouve derrière l'élément cible. Il semble être null pour vous, mais ce n'est pas un problème car il semble que votre liaison ne fait pas référence à DataContext. 

    Mais cela suggère que la MenuItem ne fait pas partie de votre VisualTree ordinaire, car typiquement la DataContext est héritée de l'objet parent.

  • # 2 contient l'erreur de liaison réelle et des informations sur la liaison. Il peut en réalité être divisé en plusieurs parties.

    • Cannot find source for binding

    • with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''.

    • BindingExpression:Path=HorizontalContentAlignment;

    "Impossible de trouver la source" signifie que la liaison ne peut pas trouver l'objet source auquel se lier, et dans votre cas, cet objet source doit être {RelativeSource AncestorType={x:Type ItemsControl} (FindAncestor et AncestorLevel=1 sont les valeurs par défaut pour une RelativeSource, je les ignore donc)

    Et la dernière partie de # 2 montre la Path à laquelle vous essayez de vous lier: HorizontalContentAlignment

Donc pour résumer, quelque part dans votre code, il y a un <MenuItem> qui tente de lier sa HorizontalContentAlignment à un ItemsControl.HorizontalContentAlignment, mais la liaison ne trouve pas la ItemsControl.

Vous utilisez une liaison RelativeSource FindAncestor pour rechercher la variable ItemsControl, qui effectue une recherche dans l'arbre visuel pour rechercher la variable ItemsControl la plus proche. Elle ne la trouve pas. Il ne doit donc pas y avoir de ItemsControl dans la hiérarchie VisualTree à partir de la variable MenuItem.

Je vois souvent ce problème avec ContextMenus car ils ne font pas partie de la même VisualTree que le reste de votre code XAML. (Pour référencer l'objet dans la variable VisualTree principale à laquelle une variable ContextMenu est attachée, vous pouvez utiliser la propriété PlacementTarget, comme cet exemple .

Une fois que vous avez compris l’erreur de liaison, il est souvent facile de trouver la source de celle-ci dans votre XAML. 

En fonction de la taille de mon application, je fais généralement l'une des choses suivantes:

  • Recherchez dans "l'application" l'élément "de l'erreur de liaison (dans votre cas, MenuItem) et voyez si l'un d'entre eux définit la" propriété cible "(HorizontalContentAlignment) avec une liaison.

  • Recherchez dans l'application la "propriété cible" de l'erreur de liaison (HorizontalContentAlignment) pour rechercher la liaison à l'origine de ce problème.

  • Recherchez dans l'application quelque chose d'assez unique parmi le texte de liaison indiqué dans l'erreur de liaison. Dans votre cas, vous pouvez essayer de rechercher sur {x:Type ItemsControl} qui ferait partie de votre liaison RelativeSource et il ne devrait pas y avoir trop de résultats de recherche pour une telle phrase.

  • Utilisez un outil tiers tel que Snoop ou WPF Inspector pour localiser l'erreur de liaison au moment de l'exécution.

    Je n'avais auparavant utilisé que Snoop, mais pour l'utiliser, vous devez démarrer votre application et l'exécuter pour l'examiner afin d'inspecter VisualTree de votre application pendant son exécution. Vous pouvez ensuite effectuer une recherche dans VisualTree en tapant quelque chose comme "MenuItem" dans la barre de recherche pour filtrer l’arborescence visuelle de toutes les MenuItems, puis parcourez leurs propriétés pour trouver celle qui présente une erreur de liaison (la propriété HorizontalContentAlignment sera surlignée en rouge car de l'erreur de liaison). 

    Il est à noter que si votre MenuItem est dans une ContextMenu, vous devez alors ouvrir cette ContextMenu pour que les éléments de menu soient dessinés et affichés dans Snoop.

88
Rachel

Peut-être que vous pourriez utiliser cette excellente application nommée Snoop . C'est gratuit dans CodePlex . Cela m'aide à trouver plusieurs problèmes de liaison et les contextes de données manquantes. Il permet d’explorer l’ensemble de l’arborescence visuelle WPF et de vous donner les erreurs de liaison.

Hope Snoop pourrait vous aider.

4
Raúl Otaño

Je suis nouveau sur WPF et j'ai exactement la même erreur. Bien que je l'ait corrigé maintenant, je ne sais vraiment pas comment ... Voici les étapes que j'ai essayées: 

Tout d'abord, j'ai:

  1. un <Menu>
  2. 2 <ContextMenu> défini dans <ListBox.ItemTemplate> 

J'ai essayé de:

  1. déplacer un <ContextMenu> dans <ListBox.ItemContainerStyle> -> erreur existe
  2. Définissez et supprimez les styles HorizontalContentAlignment et VerticalContentAlignment pour <Menu>, <ContextMenu>, <MenuItem> -> error existe
  3. Définissez l'attribut Name pour le <MenuItem> du <ContextMenu> dans <ListBox.ItemTemplate> -> aucune erreur!
  4. Supprimez l'attribut Name -> toujours pas d'erreur ...
  5. Redémarrez le VS -> l'erreur semble avoir disparu pour toujours ...

Finalement, j'ai

  1. un <Menu>
  2. un <ContextMenu> défini dans <ListBox.ItemTemplate> 
  3. un <ContextMenu> défini dans <ListBox.ItemContainerStyle> 

et NONE d’eux n’ont défini le style HorizontalContentAlignment et VerticalContentAlignment. Et l'erreur est partie ...

On dirait qu'il y a un problème d'actualisation. Donc, pour ceux qui ont le même problème, vous pouvez essayer de redémarrer le VS ou définir l'attribut Name pour le <MenuItem>...

1
Siamca