¿Cómo lo uso RelativeSource
con enlaces WPF y cuáles son los diferentes casos de uso?
.net
wpf
xaml
data-binding
relativesource
David Schmitt
fuente
fuente
AncestorType
.FindAncestor
, antesAncestorType
, aparece el siguiente error: "RelativeSource no está en modo FindAncestor". (En VS2013, versión comunitaria){Binding Path=DataContext.SomeProperty, RelativeSource=...
. Esto fue algo inesperado para mí como novato cuando intentaba vincularme al DataContext de un padre dentro de un DataTemplate.El atributo predeterminado de
RelativeSource
es laMode
propiedad. Aquí se proporciona un conjunto completo de valores válidos ( de MSDN ):PreviousData Le permite vincular 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 Hace referencia al elemento al que se aplica la plantilla (en la que existe el elemento enlazado a datos). Esto es similar a establecer una extensión de TemplateBinding y solo es aplicable si el enlace está dentro de una plantilla.
Auto Se refiere al elemento en el que está estableciendo 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 padre 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.
fuente
Aquí hay una explicación más visual en el contexto de una arquitectura MVVM:
fuente
{Binding Message}
(un poco más simple ...)Path=DataContext.Message
para que el enlace funcione. Esto tiene sentido, dado que puede hacer enlaces relativos a ancho / alto / etc. de un control.Bechir Bejaoui expone los casos de uso de RelativeSources en WPF en su artículo aquí :
fuente
ListView
. El padre tiene 2ListView
niveles más por debajo. Esto me ayudó a prevenir el contagio de datos en cada máquina virtual posterior de cadaListView
'sDataTemplate
En WPF, el
RelativeSource
enlace expone tresproperties
para establecer:1. Modo: este
enum
podría tener cuatro valores:2.
FindAncestor
Tipo de antepasado : cuando el modo es , defina qué tipo de antepasado3. AncestorLevel: cuando mode es
FindAncestor
entonces qué nivel de ancestro (si hay dos tipos de padres en el mismovisual tree
)Aquí hay un enlace de referencia .
fuente
No te olvides de TemplatedParent:
o
fuente
Vale la pena señalar que para aquellos que se encuentran con este pensamiento de Silverlight:
Silverlight ofrece solo un subconjunto reducido, de estos comandos
fuente
Creé una biblioteca para simplificar la sintaxis de enlace de WPF, lo que facilita el uso de RelativeSource. Aquí hay unos ejemplos. Antes de:
Después:
Aquí hay un ejemplo de cómo se simplifica el enlace de métodos. Antes de:
Después:
Puede encontrar la biblioteca aquí: http://www.simplygoodcode.com/2012/08/simpler-wpf-binding.html
Tenga en cuenta en el ejemplo 'ANTES' que uso para el enlace del método que el código ya estaba optimizado usando
RelayCommand
el último que verifiqué que no es una parte nativa de WPF. Sin eso, el ejemplo 'ANTES' hubiera sido aún más largo.fuente
Algunas partes útiles:
Aquí se explica cómo hacerlo principalmente en código:
Copié esto en gran parte de Binding Relative Source en el código Behind .
Además, la página MSDN es bastante buena en lo que respecta a los ejemplos: Clase RelativeSource
fuente
Acabo de publicar otra solución para acceder al DataContext de un elemento padre en Silverlight que funciona para mí. Lo utiliza
Binding ElementName
.fuente
No leí todas las respuestas, pero solo quiero agregar esta información en caso de un comando de fuente relativa de un botón.
Cuando utiliza una fuente relativa con
Mode=FindAncestor
, el enlace debe ser como:Si no agrega DataContext en su ruta, en el momento de la ejecución no puede recuperar la propiedad.
fuente
Este es un ejemplo del uso de este patrón que funcionó para mí en cuadrículas de datos vacías.
fuente
Si un elemento no es parte del árbol visual, RelativeSource nunca funcionará.
En este caso, debe probar una técnica diferente, iniciada por Thomas Levesque.
Tiene la solución en su blog en [WPF] Cómo enlazar a datos cuando el DataContext no se hereda . ¡Y funciona absolutamente brillante!
En el improbable caso de que su blog esté caído, el Apéndice A contiene una copia espejo de su artículo .
Por favor no comente aquí, comente 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 necesita configurarlo de nuevo en cada elemento que desee vincular. Sin embargo, en algunos casos el DataContext no es accesible: sucede para elementos que no son parte del árbol visual o lógico. Puede ser muy difícil vincular una propiedad a esos elementos ...
Vamos a ilustrar 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, según el valor de una propiedad ShowPrice expuesta por ViewModel. El enfoque obvio es vincular la Visibilidad de la columna a la propiedad ShowPrice:
Desafortunadamente, cambiar el valor de ShowPrice no tiene ningún efecto, y la columna siempre está visible ... ¿por qué? Si miramos la ventana Salida en Visual Studio, notamos la siguiente línea:
Podemos intentar ajustar el enlace para obtener el resultado deseado, por ejemplo, estableciendo RelativeSource en 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:
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 código subyacente, que generalmente preferimos evitar al usar el patrón MVVM ... Pero no me voy a rendir tan pronto, al menos no mientras que hay otras opciones a considerar 😉
La solución a nuestro problema es realmente 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 sé el mecanismo exacto que permite este comportamiento, pero vamos a aprovecharlo para que nuestro enlace funcione ...
La idea es crear una clase (la llamé BindingProxy por razones que deberían ser obvias muy pronto) que hereda Freezable y declara una propiedad de dependencia de datos:
Luego podemos declarar una instancia de esta clase en los recursos de DataGrid y vincular la propiedad Data al DataContext actual:
El último paso es especificar este objeto BindingProxy (de fácil acceso con StaticResource) como el origen del enlace:
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.
fuente