Question Comment utiliser les liaisons WPF avec RelativeSource?


Comment est-ce que j'utilise RelativeSource avec les liaisons WPF et quels sont les différents cas d'utilisation?


520
2017-09-17 15:10


origine


Réponses:


Si vous voulez lier à une autre propriété sur l'objet:

{Binding Path=PathToProperty, RelativeSource={RelativeSource Self}}

Si vous voulez obtenir une propriété sur un ancêtre:

{Binding Path=PathToProperty,
    RelativeSource={RelativeSource AncestorType={x:Type typeOfAncestor}}}

Si vous souhaitez obtenir une propriété sur le parent basé sur un modèle (vous pouvez ainsi créer des liaisons bidirectionnelles dans un ControlTemplate)

{Binding Path=PathToProperty, RelativeSource={RelativeSource TemplatedParent}}

ou, plus court (cela ne fonctionne que pour les liaisons OneWay):

{TemplateBinding Path=PathToProperty}

695
2017-09-17 15:14



Binding RelativeSource={
    RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemType}
}
...

L'attribut par défaut de RelativeSource est le Mode propriété. Un ensemble complet de valeurs valides est donné ici (à partir de MSDN):

  • PreviousData Vous permet de lier l'élément de données précédent (pas celui qui contient l'élément de données) dans la liste des éléments de données affichés.

  • TemplatedParent Fait référence à l'élément auquel le modèle (dans lequel se trouve l'élément lié aux données) est appliqué. Cela est similaire à la définition d'un TemplateBindingExtension et n'est applicable que si la liaison est dans un modèle.

  • Soi Fait référence à l'élément sur lequel vous définissez la liaison et vous permet de lier une propriété de cet élément à une autre propriété du même élément.

  • FindAncestor Fait référence à l'ancêtre dans la chaîne parente de l'élément lié aux données. Vous pouvez l'utiliser pour vous lier à un ancêtre d'un type spécifique ou à ses sous-classes. C'est le mode que vous utilisez si vous voulez spécifier AncestorType et / ou AncestorLevel.


122
2018-03-03 09:24



Voici une explication plus visuelle dans le contexte d'une architecture MVVM:

enter image description here


113
2018-03-16 02:35



Imaginez ce cas, un rectangle que l'on veut que sa hauteur soit toujours égale à sa largeur, un carré disons. Nous pouvons le faire en utilisant le nom de l'élément

<Rectangle Fill="Red" Name="rectangle" 
                    Height="100" Stroke="Black" 
                    Canvas.Top="100" Canvas.Left="100"
                    Width="{Binding ElementName=rectangle,
                    Path=Height}"/>

Mais dans ce cas ci-dessus, nous sommes obligés d'indiquer le nom de l'objet de liaison, à savoir le rectangle. Nous pouvons atteindre le même but différemment en utilisant RelativeSource

<Rectangle Fill="Red" Height="100" 
                   Stroke="Black" 
                   Width="{Binding RelativeSource={RelativeSource Self},
                   Path=Height}"/>

Dans ce cas, nous ne sommes pas obligés de mentionner le nom de l'objet de liaison et la largeur sera toujours égale à la hauteur chaque fois que la hauteur est modifiée.

Si vous voulez paramétrer la largeur à la moitié de la hauteur, vous pouvez le faire en ajoutant un convertisseur à l'extension Binding Binding. Imaginons un autre cas maintenant:

 <TextBlock Width="{Binding RelativeSource={RelativeSource Self},
                   Path=Parent.ActualWidth}"/>

Le cas ci-dessus est utilisé pour lier une propriété donnée d'un élément donné à l'un de ses éléments parents directs car cet élément contient une propriété appelée Parent. Cela nous amène à un autre mode source relatif, celui de FindAncestor.


40
2017-11-09 05:47



Bechir Bejaoui expose les cas d'utilisation des RelativeSources dans WPF son article ici:

RelativeSource est une extension de balisage utilisée en particulier   cas de liaison lorsque nous essayons de lier une propriété d'un objet donné à   une autre propriété de l'objet lui-même, lorsque nous essayons de lier une propriété   d'un objet à un autre de ses parents relatifs, lors de la liaison d'un   valeur de la propriété de dépendance à un morceau de XAML en cas de contrôle personnalisé   développement et enfin en cas d'utilisation d'un différentiel d'une série de   une donnée liée. Toutes ces situations sont exprimées en tant que source relative   modes. Je vais exposer tous ces cas un par un.

  1. Mode Self:

Imaginez ce cas, un rectangle que nous voulons que sa hauteur soit toujours   égal à sa largeur, un carré disons. Nous pouvons le faire en utilisant le   nom de l'élément

<Rectangle Fill="Red" Name="rectangle" 
                Height="100" Stroke="Black" 
                Canvas.Top="100" Canvas.Left="100"
                Width="{Binding ElementName=rectangle,
                Path=Height}"/>

Mais dans ce cas ci-dessus, nous sommes obligés d'indiquer le nom du   objet de liaison, à savoir le rectangle. Nous pouvons atteindre le même objectif   différemment en utilisant le RelativeSource

<Rectangle Fill="Red" Height="100" 
               Stroke="Black" 
               Width="{Binding RelativeSource={RelativeSource Self},
               Path=Height}"/>

Pour ce cas, nous ne sommes pas obligés de mentionner le nom de la liaison   objet et la largeur sera toujours égale à la hauteur à chaque fois que le   la hauteur est modifiée.

Si vous voulez paramétrer la largeur à la moitié de la hauteur alors   vous pouvez le faire en ajoutant un convertisseur à l'extension Binding Binding.   Imaginons un autre cas maintenant:

 <TextBlock Width="{Binding RelativeSource={RelativeSource Self},
               Path=Parent.ActualWidth}"/>

Le cas ci-dessus est utilisé pour attacher une propriété donnée d'un élément donné à   l'un de ses parents directs que cet élément détient une propriété qui est   appelé Parent. Cela nous amène à un autre mode de source relative qui est   le FindAncestor.

  1. Mode FindAncestor

Dans ce cas, une propriété d'un élément donné sera liée à l'un de ses   parents, de corse. La principale différence avec le cas ci-dessus est le fait   cela, c'est à vous de déterminer le type d'ancêtre et l'ancêtre   classer dans la hiérarchie pour lier la propriété. Au fait, essayez de jouer avec   ce morceau de XAML

<Canvas Name="Parent0">
    <Border Name="Parent1"
             Width="{Binding RelativeSource={RelativeSource Self},
             Path=Parent.ActualWidth}"
             Height="{Binding RelativeSource={RelativeSource Self},
             Path=Parent.ActualHeight}">
        <Canvas Name="Parent2">
            <Border Name="Parent3"
            Width="{Binding RelativeSource={RelativeSource Self},
           Path=Parent.ActualWidth}"
           Height="{Binding RelativeSource={RelativeSource Self},
              Path=Parent.ActualHeight}">
               <Canvas Name="Parent4">
               <TextBlock FontSize="16" 
               Margin="5" Text="Display the name of the ancestor"/>
               <TextBlock FontSize="16" 
                 Margin="50" 
            Text="{Binding RelativeSource={RelativeSource  
                       FindAncestor,
                       AncestorType={x:Type Border}, 
                       AncestorLevel=2},Path=Name}" 
                       Width="200"/>
                </Canvas>
            </Border>
        </Canvas>
     </Border>
   </Canvas>

La situation ci-dessus est de deux éléments TextBlock ceux qui sont incorporés   dans une série de frontières et des éléments de toile ceux-ci représentent leur   parents hiérarchiques. Le second TextBlock affichera le nom de   le parent donné au niveau de la source relative.

Alors essayez de changer AncestorLevel = 2 à AncestorLevel = 1 et voyez ce que   arrive. Ensuite, essayez de changer le type de l'ancêtre de   AncestorType = Border to AncestorType = Canvas et voir ce qu'il se passe.

Le texte affiché changera en fonction du type Ancêtre et   niveau. Alors qu'est-ce qui se passe si le niveau de l'ancêtre ne convient pas à la   type d'ancêtre? C'est une bonne question, je sais que vous êtes sur le point de   demande-le. La réponse est aucune exception sera jeté et rien ne sera   être affiché au niveau TextBlock.

  1. TemplatedParent

Ce mode permet de lier une propriété ControlTemplate donnée à une propriété   du contrôle auquel le ControlTemplate est appliqué. À bien   comprendre le problème ici est un exemple ci-dessous

<Window.Resources>
<ControlTemplate x:Key="template">
        <Canvas>
            <Canvas.RenderTransform>
                <RotateTransform Angle="20"/>
                </Canvas.RenderTransform>
            <Ellipse Height="100" Width="150" 
                 Fill="{Binding 
            RelativeSource={RelativeSource TemplatedParent},
            Path=Background}">

              </Ellipse>
            <ContentPresenter Margin="35" 
                  Content="{Binding RelativeSource={RelativeSource  
                  TemplatedParent},Path=Content}"/>
        </Canvas>
    </ControlTemplate>
</Window.Resources>
    <Canvas Name="Parent0">
    <Button   Margin="50" 
              Template="{StaticResource template}" Height="0" 
              Canvas.Left="0" Canvas.Top="0" Width="0">
        <TextBlock FontSize="22">Click me</TextBlock>
    </Button>
 </Canvas>

Si je veux appliquer les propriétés d'un contrôle donné à son contrôle   modèle alors je peux utiliser le mode TemplatedParent. Il y a aussi   similaire à cette extension de balisage qui est le TemplateBinding   qui est une sorte de main courte du premier, mais le   TemplateBinding est évalué au moment de la compilation au contraste du   TemplatedParent qui est évalué juste après la première exécution. Comme   vous pouvez remarquer dans la figure ci-dessous, l'arrière-plan et le contenu   sont appliqués depuis le bouton jusqu'au gabarit de contrôle.


34
2017-10-19 20:34



Ne pas oublier TemplatedParent:

<Binding RelativeSource="{RelativeSource TemplatedParent}"/>

ou

{Binding RelativeSource={RelativeSource TemplatedParent}}

17
2017-09-17 15:14



Dans WPF RelativeSource reliure expose trois properties mettre en place:

1. mode: C'est un enum cela pourrait avoir quatre valeurs:

une. Données précédentes (value=0): Il affecte la valeur précédente du property à   le lié

b. TemplatedParent (value=1):  Ceci est utilisé lors de la définition du templates de   tout contrôle et que vous souhaitez lier à une valeur / propriété du control.

Par exemple, définir ControlTemplate:

  <ControlTemplate>
        <CheckBox IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
 </ControlTemplate>

c. Soi(value=2): Quand on veut lier d'un self ou un property De soi.

Par exemple: Envoyer l'état vérifié de checkbox comme CommandParameter en réglant le Command sur CheckBox

<CheckBox ...... CommandParameter="{Binding RelativeSource={RelativeSource Self},Path=IsChecked}" />

ré. FindAncestor (value=3): Lorsque vous voulez lier d'un parent control   dans Visual Tree.

Par exemple: Lier un checkbox dans records si un grid,si header  checkbox est vérifié

<CheckBox IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type iDP:XamDataGrid}}, Path=DataContext.IsHeaderChecked, Mode=TwoWay}" />

2. AncestorType:  quand le mode est FindAncestor puis définissez quel type d'ancêtre

RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type iDP:XamDataGrid}}

3. Niveau d'Ancêtre:  quand le mode est FindAncestor alors quel niveau d'ancêtre (s'il y a deux types de parents visual tree)

RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type iDP:XamDataGrid, AncestorLevel=1}}

Ci-dessus sont tous les cas d'utilisation pour RelativeSource binding.

Voici un lien de référence.


14
2018-01-21 13:41



Il est digne de remarque que pour ceux qui trébuchent à travers cette pensée de Silverlight:

Silverlight propose uniquement un sous-ensemble réduit de ces commandes


13
2018-04-24 16:02