Que fait exactement le "RelativeSource FindAncestor" de WPF Data Binding?
je travaille actuellement dans un contrôle d'utilisateur WPF (l'élément racine de mon fichier XAML est "UserControl"), dont je sais qu'il est hébergé dans une fenêtre. Comment puis-je accéder à une propriété de la fenêtre en utilisant data binding?
Est-ce que quelqu'un sait pourquoi simplement
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type Window}}" Path="..." />
ne fonctionne pas? Le message d'erreur que je reçois est:
Système.Windows.Avertissement de données: 4: Impossible de trouver la source pour la liaison avec la référence 'RelativeSource FindAncestor, AncestorType=' système.Windows.Fenêtre", Niveau d'ancêtre= '1".
Edit: j'ai fini par utiliser une variante de L'approche D'ArsenMkrt, donc j'ai accepté sa réponse. Cependant, je suis toujours intéressé à savoir pourquoi FindAncestor ne "fonctionne pas seulement".
3 réponses
La meilleure façon est de donner un nom à UserControl
Créer une dépendance de la propriété MyProperty dans UserControl avec une liaison bidirectionnelle et à l'engager dans la Fenêtre principale, que lient dans UserControl comme ceci
<UserControl x:Name = "myControl">
<Label Content={Binding ElementName= myControl, Path=MyProperty}/>
</UserControl>
si vous essayez de "vous échapper" d'un ItemsControl
ou DataGridView
pour obtenir un Window
vous pouvez peut-être trouver que AncestorType de x:Type Window
ne fonctionne pas. Ou au moins ne semble pas...
si c'est le cas, vous utilisez probablement Blend ou Visual Studio et vous attendez à ce que les données soient visibles au moment de la conception - ce qui n'est pas le cas parce que VS + Blend crée leurs propres instances qui ne sont pas vraiment des fenêtres. Il fonctionnera à l'exécution tout simplement bien, mais pas pendant la conception mode.
Il ya un couple de choses que vous pouvez faire:
Enveloppez-les dans un UserControl
Voici une solution alternative que j'ai trouvé. Il a un avantage en ce que vous ne faites pas référence à un
UserControl
ouWindow
directement, donc si vous changez le conteneur parent votre code ne se cassera pas.<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:views="clr-namespace:MyWPFApplication.Views" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="MyWPFApplication.Views.UPCLabelPrinterWindow" mc:Ignorable="d" x:Name="LayoutRoot" Title="UPCLabelPrinterWindow"> <views:DataContextWrapper> <DockPanel> ... </DockPanel> </views:DataContextWrapper>
Où DataContextWrapper
est juste une grille
namespace MyWPFApplication.Views {
public class DataContextWrapper : Grid
{
}
}
puis quand vous liez pour ce faire :
<TextBlock Text="{Binding="{Binding DataContext.SomeText,
RelativeSource={RelativeSource AncestorType={x:Type views:DataContextWrapper},
Mode=FindAncestor}}" />
Note: Si vous voulez lier une propriété sur la fenêtre elle-même, c'est plus compliqué et vous devriez probablement le faire via une propriété de dépendance ou quelque chose comme ça. Mais si vous utilisez MVVM alors c'est une solution que j'ai trouvé.
je Pense que Vous Devriez mettre en Mode="OneWayToSource" Comme ceci:
<TextBox Text="{Binding RelativeSource={RelativeSource FindAncestor ,AncestorType={x:Type Grid}},Path=BackGround , Mode=OneWayToSource , UpdateSourceTrigger = PropertyChanged}" />