Pregunta ¿Cómo uso enlaces WPF con RelativeSource?


Cómo uso RelativeSource con enlaces WPF y ¿cuáles son los diferentes casos de uso?


520
2017-09-17 15:10


origen


Respuestas:


Si desea enlazar a otra propiedad en el objeto:

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

Si desea obtener una propiedad de un antepasado:

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

Si desea obtener una propiedad en el padre con plantilla (para que pueda hacer enlaces bidireccionales en una plantilla ControlTemplate)

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

o, más corto (esto solo funciona para enlaces OneWay):

{TemplateBinding Path=PathToProperty}

695
2017-09-17 15:14



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

El atributo predeterminado de RelativeSource es el Mode propiedad. Aquí se proporciona un conjunto completo de valores válidos (de MSDN)

  • PreviousData Le permite vincular el elemento de datos anterior (no el control que contiene el elemento de datos) en la lista de elementos de datos que se muestran.

  • TemplatedParent Se refiere al elemento al que se aplica la plantilla (en la que existe el elemento vinculado a los datos). Esto es similar a establecer una TemplateBindingExtension y solo es aplicable si el enlace está dentro de una plantilla.

  • Yo Se refiere al elemento en el que está configurando el enlace y le permite vincular una propiedad de ese elemento a otra propiedad en el mismo elemento.

  • FindAncestor Se refiere al antecesor en la cadena primaria del elemento vinculado a datos. Puede usar esto para enlazar a un antecesor de un tipo específico o sus subclases. Este es el modo que usa si quiere especificar AncestorType y / o AncestorLevel.


122
2018-03-03 09:24



Aquí hay una explicación más visual en el contexto de una arquitectura MVVM:

enter image description here


113
2018-03-16 02:35



Imagina este caso, un rectángulo que queremos que su altura sea siempre igual a su ancho, digamos un cuadrado. Podemos hacer esto usando el nombre del elemento

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

Pero en este caso anterior estamos obligados a indicar el nombre del objeto vinculante, es decir, el rectángulo. Podemos alcanzar el mismo propósito de manera diferente usando RelativeSource

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

Para ese caso no estamos obligados a mencionar el nombre del objeto vinculante y el ancho siempre será igual al alto cada vez que se cambie la altura.

Si desea parametrizar el ancho para que sea la mitad de la altura, puede hacerlo agregando un convertidor a la extensión de marcado de encuadernación. Imaginemos otro caso ahora:

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

El caso anterior se utiliza para vincular una propiedad dada de un elemento dado con uno de sus elementos primarios directos, ya que este elemento contiene una propiedad que se llama Principal. Esto nos lleva a otro modo fuente relativo que es FindAncestor.


40
2017-11-09 05:47



Bechir Bejaoui expone los casos de uso de RelativeSources en WPF en su artículo aquí:

RelativeSource es una extensión de marcado que se usa en particular   casos vinculantes cuando tratamos de vincular una propiedad de un objeto dado a   otra propiedad del objeto en sí, cuando tratamos de vincular una propiedad   de un objeto a otro de sus padres relativos, al vincular un   valor de propiedad de dependencia a una pieza de XAML en caso de control personalizado   desarrollo y, finalmente, en el caso de utilizar un diferencial de una serie de   un enlace de datos. Todas esas situaciones se expresan como fuente relativa   modos. Expondré todos esos casos uno por uno.

  1. Modo Self:

Imagina este caso, un rectángulo que queremos que su altura sea siempre   igual a su ancho, un cuadrado digamos. Podemos hacer esto usando el   nombre del elemento

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

Pero en este caso, estamos obligados a indicar el nombre del   objeto vinculante, es decir, el rectángulo. Podemos alcanzar el mismo objetivo   de manera diferente usando RelativeSource

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

Para ese caso no estamos obligados a mencionar el nombre del enlace   objeto y el ancho será siempre igual a la altura cada vez que el   la altura es cambiada

Si quiere parametrizar el ancho para que sea la mitad de la altura, entonces   puede hacer esto agregando un convertidor a la extensión de marcado de encuadernación.   Imaginemos otro caso ahora:

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

El caso anterior se usa para vincular una propiedad dada de un elemento dado a   uno de sus padres directos ya que este elemento tiene una propiedad que es   llamado Parent. Esto nos lleva a otro modo fuente relativo que es   el FindAncestor uno.

  1. Modo FindAncestor

En este caso, una propiedad de un elemento dado estará vinculada a uno de sus   padres, de Corse. La principal diferencia con el caso anterior es el hecho   eso, depende de ti determinar el tipo de ancestro y el ancestro   rango en la jerarquía para vincular la propiedad. Por cierto, intenta jugar con   esta pieza 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 situación anterior es de dos elementos TextBlock que están incrustados   dentro de una serie de fronteras y elementos de lona que representan su   padres jerárquicos El segundo TextBlock mostrará el nombre de   el padre dado en el nivel de fuente relativa.

Intente cambiar AncestorLevel = 2 a AncestorLevel = 1 y vea qué   sucede. Luego intente cambiar el tipo de ancestro de   AncestorType = Border a AncestorType = Canvas y mira lo que sucede.

El texto mostrado cambiará de acuerdo con el tipo de Antepasado y   nivel. Entonces, ¿qué sucede si el nivel ancestro no es adecuado para el   tipo ancestro? Esta es una buena pregunta, sé que estás a punto de   preguntalo La respuesta es que no se lanzarán excepciones y nada   se mostrará en el nivel TextBlock.

  1. TemplatedParent

Este modo permite vincular una propiedad determinada de ControlTemplate a una propiedad   del control al que se aplica ControlTemplate Para bien   entender el problema aquí es un ejemplo abajo

<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 quiero aplicar las propiedades de un control dado a su control   plantilla, entonces puedo usar el modo TemplatedParent. También hay una   similar a esta extensión de marcado que es el TemplateBinding   que es una especie de mano corta del primero, pero el   TemplateBinding se evalúa en tiempo de compilación en el contraste de la   TemplatedParent que se evalúa justo después del primer tiempo de ejecución. Como   puedes comentar en la figura de abajo, el fondo y el contenido   se aplican desde el botón a la plantilla de control.


34
2017-10-19 20:34



No te olvides de TemplatedParent:

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

o

{Binding RelativeSource={RelativeSource TemplatedParent}}

17
2017-09-17 15:14



En WPF RelativeSource encuadernación expone tres properties para establecer:

1. Modo: Esto es un enum eso podría tener cuatro valores:

a. PreviousData (value=0) Asigna el valor anterior de la property a   el obligado

segundo. TemplatedParent (value=1)  Esto se usa cuando se define el templates de   cualquier control y desea vincular a un valor / propiedad de la control.

Por ejemplo, definir ControlTemplate:

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

do. Yo(value=2) Cuando queremos vincular desde un self o una property de sí mismo.

Por ejemplo: Enviar estado verificado de checkbox como CommandParameter mientras configura el Command en CheckBox

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

re. FindAncestor (value=3) Cuando quiere vincularse desde un padre control   en Visual Tree.

Por ejemplo: Enlazar checkbox en records si un grid,Si header  checkbox está chequeado

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

2. AncestorType:  cuando el modo es FindAncestor luego define qué tipo de ancestro

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

3. Ancestro Nivel:  cuando el modo es FindAncestor entonces, ¿qué nivel de ancestro (si hay dos tipos de padres iguales en visual tree)

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

Arriba están todos los casos de uso para RelativeSource binding.

Aquí hay un enlace de referencia.


14
2018-01-21 13:41