14 Pregunta: ¿Cómo uso los enlaces WPF con RelativeSource?

pregunta creada en Fri, Oct 2, 2015 12:00 AM

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

    
550
14 Respuestas                              14                         

Si desea enlazar a otra propiedad en el objeto:

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

Si desea obtener una propiedad sobre 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 de dos vías en una ControlTemplate)

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

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

 
{TemplateBinding Path=PathToProperty}
    
736
2017-01-31 09: 26: 46Z
  1. Para este "{Binding Path = PathToProperty, RelativeSource = {RelativeSource AncestorType = {x: Type typeOfAncestor}}}", parece que necesita tener "Modo = FindAncestor, "antes de" AncestorType "
    2017-02-02 21: 12: 25Z
  2. ¿Para qué tecnología? En WPF, eso se deduce cuando se especifica un AncestorType.
    2017-02-07 21: 13: 29Z
  3. Estoy de acuerdo con @EdwardM. Cuando omito FindAncestor, antes de AncestorType, aparece el siguiente error: "RelativeSource no está en modo FindAncestor". (En VS2013, versión comunitaria)
    2017-04-10 03: 40: 36Z
  4. @ kmote, esto ha funcionado para mí desde .net 3.0, y una vez más verifiqué que funciona de esta manera en kaxaml ... De nuevo, ¿qué tecnología estás usando? ? El procesador XAML es diferente para WPF /Silverlight /UWP, por lo que puede tener diferentes resultados en diferentes tecnologías. También mencionó a VS Community, así que quizás sea una advertencia IDE, ¿pero funciona en tiempo de ejecución?
    2017-04-17 20: 01: 53Z
  5. Quería señalar aquí que si desea enlazar a una propiedad en el DataContext de RelativeSource, debe especificarlo explícitamente: {Binding Path=DataContext.SomeProperty, RelativeSource=.... Esto fue algo inesperado para mí como novato cuando intentaba enlazar el DataContext de un padre dentro de una DataTemplate.
    2018-11-13 19: 04: 45Z
 
Binding RelativeSource={
    RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemType}
}
...

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

  • PreviousData Le permite enlazar el elemento de datos anterior (no ese 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 enlazado a datos). Esto es similar a establecer una TemplateBindingExtension y solo es aplicable si el enlace está dentro de una plantilla.

  • Self 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 antepasado en la cadena principal del elemento enlazado a datos. Puede usar esto para enlazar a un antepasado de un tipo específico o sus subclases. Este es el modo que utiliza si desea especificar AncestorType y /o AncestorLevel.

126
2009-03-03 09: 24: 23Z

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

ingrese la descripción de la imagen aquí

    
120
2012-02-05 21: 43: 26Z
  1. ¿me perdí algo? ¿Cómo puedes considerar que un gráfico simple y claro? 1: los cuadros en el significado de la izquierda no están realmente relacionados con los de la derecha (¿por qué hay un archivo .cs dentro del ViewModel?) 2: ¿a qué apuntan estas flechas de DataContext? 3: ¿por qué la propiedad Message no está en ViewModel1? y lo más importante, 5: ¿Por qué necesita un enlace RelativeSource para llegar al DataContext de la ventana si el TextBlock ya tiene ese mismo DataContext? Claramente, me estoy perdiendo algo, así que, ¡o bien soy bastante tonto o este gráfico no es tan simple y claro como todos piensan! Por favor, ilumíname
    2016-07-08 18: 09: 38Z
  2. @ MarkusHütter El diagrama muestra a un grupo unas Vistas anidadas y los ViewModels correspondientes. El DataContext de View1 es ViewModel1, pero quiere enlazar a una propiedad de BaseViewModel. Debido a que BaseViewModel es el DataContext de BaseView (que es una ventana), puede hacerlo buscando el primer contenedor primario que es una ventana y tomando su DataContext.
    2016-07-22 14: 37: 31Z
  3. @ MatthewCargille Sé muy bien lo que se supone que significa , ese no era mi punto. Pero ubícate en la posición de alguien que no conoce bien XAML y MVVM y verás que esto no es simple y claro .
    2016-07-22 18: 36: 26Z
  4. Estoy de acuerdo con @ MarkusHütter, por cierto, el enlace de la izquierda podría ser tan simple como este: {Binding Message} (un poco más simple ...)
    2017-08-17 16: 55: 19Z
  5. @ florien No lo creo, al menos para mi caso de uso. Tengo un DataTemplate que necesita referirme al DataContext de MainWindow (mi clase de viewmodel) para obtener una lista de opciones para un menú desplegable (cargado desde una base de datos). La plantilla de datos está vinculada a un objeto modelo que también se carga desde la base de datos, pero solo tiene acceso a la opción seleccionada. Tuve que establecer explícitamente Path=DataContext.Message para que el enlace funcione. Esto tiene sentido, dado que puede hacer enlaces relativos a ancho /alto /etc. de un control.
    2018-11-13 18: 37: 44Z

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 de enlace, es decir, el rectángulo. Podemos alcanzar el mismo propósito de manera diferente utilizando RelativeSource

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

En ese caso, no estamos obligados a mencionar el nombre del objeto de enlace y el Ancho siempre será igual a la Altura siempre 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 vinculació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 una de sus propiedades principales directas, ya que este elemento contiene una propiedad que se llama principal. Esto nos lleva a otro modo de fuente relativa que es el FindAncestor.

    
40
2012-11-09 05: 47: 07Z
  1. Es mejor citar su fuente cuando copia y pega.
    2014-12-14 03: 20: 55Z
  2. @ Jeremy se refiere a este tutorial por Bechir Bejaoui a partir del 11 de mayo de 2010.
    2017-03-30 16: 02: 22Z
  3. @ ZachMierzejewski Gracias, la respuesta de SO dice que faltan párrafos y hay ejemplos.
    2017-09-06 00: 51: 00Z

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

  

El RelativeSource es una extensión de marcado que se usa en particular   casos vinculantes cuando intentamos vincular una propiedad de un objeto dado a   Otra propiedad del objeto en sí, cuando intentamos enlazar una propiedad.   de un objeto a otro de sus padres relativos, al vincular un   valor de la propiedad de dependencia a una parte de XAML en caso de control personalizado   desarrollo y, finalmente, en caso de utilizar un diferencial de una serie de   Un dato encuadernado. Todas esas situaciones se expresan como fuente relativa.   modos Expondré todos esos casos uno por uno.

     
  1. Modo Auto:
  2.   

Imagina este caso, un rectángulo que queremos que su altura sea siempre   igual a su anchura, 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 el RelativeSource

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

En ese caso, no estamos obligados a mencionar el nombre del enlace.   objeto y el ancho siempre será igual a la altura cuando el   Se cambia la altura.

     

Si desea 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 vinculació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 a   Uno de sus padres directos, ya que este elemento tiene una propiedad que es   llamado padre. Esto nos lleva a otro modo de fuente relativa que es   el FindAncestor uno.

     
  1. Modo FindAncestor
  2.   

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 usted determinar el tipo de antepasado y el antepasado   Rango en la jerarquía para atar 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 bordes y elementos de lienzo 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 A continuación, intente cambiar el tipo de antepasado de   AncestorType = Borde a AncestorType = Lienzo y vea qué sucede.

     

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

     
  1. TemplatedParent
  2.   

Este modo permite vincular una propiedad ControlTemplate dada a una propiedad   del control al que se aplica el ControlTemplate. A 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   Entonces la plantilla puedo usar el modo TemplatedParent. También hay una   similar a esta extensión de marcado que es el Enlace de Plantilla   que es una especie de mano corta de la primera, pero la   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 dentro del botón a la plantilla de control.

    
34
2013-11-02 16: 51: 29Z

En el enlace WPF RelativeSource se exponen tres properties para establecer:

1. Modo: Este es un enum que podría tener cuatro valores:

  

a. PreviousData (value=0): Asigna el valor anterior del property a   el encuadernado

     

b. TemplatedParent (value=1): Esto se usa al definir el templates de   Cualquier control y desea enlazar a un valor /propiedad del control.

     

Por ejemplo, define ControlTemplate:

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

c. Self (value=2): Cuando queremos enlazar desde un self o un property de self.

     

Por ejemplo: envía el estado verificado de checkbox como CommandParameter mientras configuras el Command en CheckBox

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

d. FindAncestor (value=3): cuando desee enlazar desde un padre control   en Visual Tree.

     

Por ejemplo: vincular un checkbox en records si es un grid, si header checkbox está marcado

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

2. AncestorType: cuando el modo es FindAncestor, defina qué tipo de antepasado

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

3. AncestorLevel: cuando el modo es FindAncestor, entonces qué nivel de antepasado (si hay dos padres del mismo tipo 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 .

    
24
2018-05-19 09: 24: 28Z
  1. Genial ... esto funcionó para mí: < DataGridCheckBoxColumn Header = "Paid" Width = "35" Binding = "{Binding RelativeSource = {RelativeSource Mode = FindAncestor, AncestorType = {x: Tipo de ventana}}, Ruta = DataContext.SelectedBuyer.IsPaid, Modo = OneWay} "/> donde estaba intentando enlazar con el comprador seleccionado de la ventana principal. Propiedad de pago
    2018-10-25 00: 21: 26Z

No te olvides de TemplatedParent:

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

o

 
{Binding RelativeSource={RelativeSource TemplatedParent}}
    
18
2008-09-17 15: 14: 34Z

Es digno de notar que para aquellos que tropiezan con este pensamiento de Silverlight:

Silverlight ofrece solo un subconjunto reducido, de estos comandos

    
13
2010-04-24 16: 02: 46Z
  1. Sí, también estaba buscando soporte para SL. Vota: connect. microsoft.com/VisualStudio/feedback/details/480603/…
    2010-05-18 18: 31: 52Z

Creé una biblioteca para simplificar la sintaxis de enlace de WPF, lo que incluye facilitar el uso de RelativeSource. Aquí hay unos ejemplos. Antes:

 
{Binding Path=PathToProperty, RelativeSource={RelativeSource Self}}
{Binding Path=PathToProperty, RelativeSource={RelativeSource AncestorType={x:Type typeOfAncestor}}}
{Binding Path=PathToProperty, RelativeSource={RelativeSource TemplatedParent}}
{Binding Path=Text, ElementName=MyTextBox}

Después:

 
{BindTo PathToProperty}
{BindTo Ancestor.typeOfAncestor.PathToProperty}
{BindTo Template.PathToProperty}
{BindTo #MyTextBox.Text}

Aquí hay un ejemplo de cómo se simplifica el enlace del método. Antes:

 
// C# code
private ICommand _saveCommand;
public ICommand SaveCommand {
 get {
  if (_saveCommand == null) {
   _saveCommand = new RelayCommand(x => this.SaveObject());
  }
  return _saveCommand;
 }
}

private void SaveObject() {
 // do something
}

// XAML
{Binding Path=SaveCommand}

Después:

 
// C# code
private void SaveObject() {
 // do something
}

// XAML
{BindTo SaveObject()}

Puede encontrar la biblioteca aquí: http://www.simplygoodcode.com/2012/08 /simpler-wpf-binding.html

Note en el ejemplo 'ANTES' que uso para el enlace de métodos que el código ya estaba optimizado usando RelayCommand, el último que verifiqué no es una parte nativa de WPF. Sin eso, el ejemplo 'ANTES' hubiera sido aún más largo.

    
13
2012-08-06 18: 12: 51Z
  1. Este tipo de ejercicios manuales demuestran la debilidad de XAML; camino demasiado complicado.
    2017-01-04 14: 37: 48Z

Algunos bits y piezas útiles:

Aquí se explica cómo hacerlo principalmente en código:

 
Binding b = new Binding();
b.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, this.GetType(), 1);
b.Path = new PropertyPath("MyElementThatNeedsBinding");
MyLabel.SetBinding(ContentProperty, b);

Lo copié en gran parte de Fuente relativa vinculante en el código Detrás .

Además, la página de MSDN es bastante buena en cuanto a los ejemplos: RelativeSource Class

    
12
2018-05-19 09: 23: 32Z
  1. Mi vaga memoria de WPF es que hacer enlaces en el código probablemente no sea lo mejor.
    2017-03-22 19: 58: 42Z

No leí todas las respuestas, pero solo quiero agregar esta información en caso de un enlace de comando de fuente relativa de un botón.

Cuando usa una fuente relativa con Mode=FindAncestor, el enlace debe ser como:

 
Command="{Binding Path=DataContext.CommandProperty, RelativeSource={...}}"

Si no agrega DataContext en su ruta, en el momento de la ejecución no puede recuperar la propiedad.

    
9
2018-05-18 10: 46: 55Z

Este es un ejemplo del uso de este patrón que me funcionó en áreas de datos vacías.

 
<Style.Triggers>
    <DataTrigger Binding="{Binding Items.Count, RelativeSource={RelativeSource Self}}" Value="0">
        <Setter Property="Background">
            <Setter.Value>
                <VisualBrush Stretch="None">
                    <VisualBrush.Visual>
                        <TextBlock Text="We did't find any matching records for your search..." FontSize="16" FontWeight="SemiBold" Foreground="LightCoral"/>
                    </VisualBrush.Visual>
                </VisualBrush>
            </Setter.Value>
        </Setter>
    </DataTrigger>
</Style.Triggers>
    
8
2015-04-29 13: 59: 41Z

Si un elemento no forma parte del árbol visual, RelativeSource nunca funcionará.

En este caso, debes probar una técnica diferente, desarrollada por Thomas Levesque.

Tiene la solución en su blog en [WPF] Cómo enlazar a los datos cuando el DataContext no se hereda . ¡Y funciona absolutamente brillante!

En el improbable caso de que su blog esté inactivo, el Apéndice A contiene una copia de su artículo .

Por favor, no comentes aquí, comenta directamente en su blog .

Apéndice A: espejo de la publicación del blog

La propiedad DataContext en WPF es extremadamente útil, ya que es heredada automáticamente por todos los elementos secundarios del elemento donde lo asigna; por lo tanto, no es necesario volver a establecerlo en cada elemento que desee enlazar. Sin embargo, en algunos casos, el DataContext no es accesible: sucede con los elementos que no forman parte del árbol visual o lógico. Puede ser muy difícil entonces vincular una propiedad con esos elementos ...

Ilustrémoslo con un ejemplo simple: queremos mostrar una lista de productos en un DataGrid. En la cuadrícula, queremos poder mostrar u ocultar la columna Precio, en función del valor de una propiedad ShowPrice expuesta por ViewModel. El enfoque obvio es vincular la visibilidad de la columna a la propiedad ShowPrice:

 
<DataGridTextColumn Header="Price" Binding="{Binding Price}" IsReadOnly="False"
                Visibility="{Binding ShowPrice,
                Converter={StaticResource visibilityConverter}}"/>

Lamentablemente, cambiar el valor de ShowPrice no tiene ningún efecto, y la columna siempre está visible ... ¿por qué? Si observamos la ventana de resultados en Visual Studio, notamos la siguiente línea:

  

Error de System.Windows.Data: 2: no se puede encontrar FrameworkElement o FrameworkContentElement gobernante para el elemento de destino. BindingExpression: Path = ShowPrice; DataItem = null; el elemento de destino es ‘DataGridTextColumn’ (HashCode = 32685253); la propiedad de destino es ‘Visibilidad’ (tipo ‘Visibilidad’)

     

El mensaje es bastante críptico, pero el significado es bastante simple: WPF no sabe qué FrameworkElement usar para obtener el DataContext, porque la columna no pertenece al árbol visual o lógico del DataGrid.

Podemos intentar modificar el enlace para obtener el resultado deseado, por ejemplo, estableciendo el RelativeSource en el DataGrid en sí:

 
<DataGridTextColumn Header="Price" Binding="{Binding Price}" IsReadOnly="False"
                Visibility="{Binding DataContext.ShowPrice,
                Converter={StaticResource visibilityConverter},
                RelativeSource={RelativeSource FindAncestor, AncestorType=DataGrid}}"/>

O podemos agregar un CheckBox vinculado a ShowPrice e intentar vincular la visibilidad de la columna a la propiedad IsChecked especificando el nombre del elemento:

 
<DataGridTextColumn Header="Price" Binding="{Binding Price}" IsReadOnly="False"
                Visibility="{Binding IsChecked,
                Converter={StaticResource visibilityConverter},
                ElementName=chkShowPrice}"/>

Pero ninguna de estas soluciones parece funcionar, siempre obtenemos el mismo resultado ...

En este punto, parece que el único enfoque viable sería cambiar la visibilidad de la columna en el código subyacente, que generalmente preferimos evitar cuando se usa el patrón MVVM ... Pero no voy a rendirme tan pronto. al menos no mientras haya otras opciones a considerar 😉

La solución a nuestro problema es bastante simple y aprovecha la clase Freezable. El propósito principal de esta clase es definir objetos que tienen un estado modificable y de solo lectura, pero la característica interesante en nuestro caso es que los objetos Freezable pueden heredar el DataContext incluso cuando no están en el árbol visual o lógico. No conozco el mecanismo exacto que permite este comportamiento, pero vamos a aprovecharlo para que nuestro trabajo de enlace ...

La idea es crear una clase (lo llamé BindingProxy por razones que deberían ser evidentes muy pronto) que hereda Freezable y declara una propiedad de dependencia de datos:

 
public class BindingProxy : Freezable
{
    #region Overrides of Freezable

    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    #endregion

    public object Data
    {
        get { return (object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Data.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
}

Luego podemos declarar una instancia de esta clase en los recursos del DataGrid, y vincular la propiedad Data al DataContext actual:

 
<DataGrid.Resources>
    <local:BindingProxy x:Key="proxy" Data="{Binding}" />
</DataGrid.Resources>

El último paso es especificar este objeto BindingProxy (fácilmente accesible con StaticResource) como la Fuente del enlace:

 
<DataGridTextColumn Header="Price" Binding="{Binding Price}" IsReadOnly="False"
                Visibility="{Binding Data.ShowPrice,
                Converter={StaticResource visibilityConverter},
                Source={StaticResource proxy}}"/>

Tenga en cuenta que la ruta de enlace se ha prefijado con "Datos", ya que la ruta ahora es relativa al objeto BindingProxy.

El enlace ahora funciona correctamente, y la columna se muestra u oculta correctamente según la propiedad ShowPrice.

    
4
2017-09-05 10: 46: 12Z
fuente colocada aquí