wpf xaml binding relativesource

wpf - Enlace RelativeSource desde una información sobre herramientas o ContextMenu



xaml binding (4)

Creo que debería hacerse así:

{Binding Path=Title, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"

¿Qué estoy haciendo mal aquí?:

<GridViewColumn> <GridViewColumn.CellTemplate> <DataTemplate> <Button> <Button.ToolTip> <TextBlock Text="{Binding Path=Title, RelativeSource={RelativeSource AncestorType=Window}}" />

Eso es solo un ejemplo simplificado, que no funciona de todos modos :) En realidad, necesito obtener un valor de otra propiedad que esté dentro del alcance del DataContext de la ventana.

Ayudame por favor.


Debido a que ContextMenu no está en el árbol visual, el enlace no funcionará. una solución simple es usar Proxy Pattern, puede crear una clase contenedora que hereda de DependencyObject y tiene DependencyProperty que mantendrá un DataContext de su Window , luego puede tener un recurso del proxy en XAML y finalmente enlazar su comando MenuItem con su comando deseado a través del objeto proxy.
Proxy de muestra:

Public class ProxyClass : DependencyObject { Public object Data {get; set;} public static readonly DependencyProperty DataProperty = DependencyProperty.Register("DataProperty", typeof(object), typeof(ProxyClass), new FrameworkPropertyMetadata(null)); }

Cómo usar en XAML:

<Window DataContext="{Binding MyViewModel}"> ... <Window.Resources> <ProxyClass Data={Binding} x:Key="BindingProxy"/> </Window.Resources> ... <MenuItem Command="{Binding Source={StaticResource BindingProxy}, Path=Data.MyDesiredCommand"/> ... </Window>

¿Que esta pasando?
Data propiedad de Data de ProxyClass se vinculará a DataContext of Window , y luego tendrá todas sus comandes y propiedades de su ViewModel dentro del recurso ProxyClass .
Otro beneficio de este enfoque es la portabilidad y la reutilización en múltiples vistas y proyectos.


Esto es complicado porque ToolTip no es parte del VisualTree. Here verá una solución genial para el mismo problema con ContextMenus. De la misma manera que puede ir por la información sobre herramientas.

ACTUALIZAR
Lamentablemente, el enlace se ha ido y no he encontrado el artículo referenciado más.
Por lo que recuerdo, el blog al que se hace referencia ha mostrado cómo enlazar a un DataContext de otro VisualTree, que a menudo es necesario cuando se vincula desde una información sobre herramientas, un ContextMenu o un Popup.

Una buena forma de hacerlo es proporcionar la instancia deseada (por ejemplo, ViewModel) dentro de Tag-property de PlacementTarget. El siguiente ejemplo hace esto para acceder a una instancia de comando de un ViewModel:

<Button Tag="{Binding DataContext,RelativeSource={RelativeSource Mode=Self}}"> <Button.ContextMenu> <ContextMenu> <MenuItem Command="{Binding PlacementTarget.Tag.DesiredCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu}}" .../> <ContextMenu> </Button.ContextMenu> </Button>

No lo he probado y hace mucho tiempo que hice esto la última vez. Por favor, haga un comentario si no funciona para usted.

ACTUALIZACIÓN 2

Como el enlace original del que se escribió esta respuesta se ha ido, presioné archive.org y encontré la entrada original del blog . Aquí está, textualmente del blog:

Debido a que un ContextMenu en WPF no existe dentro del árbol visual de su página / ventana / control per se, el enlace de datos puede ser un poco complicado. He buscado alto y bajo en la web para esto, y la respuesta más común parece ser "solo hazlo en el código subyacente". ¡INCORRECTO! No entré en el maravilloso mundo de XAML para volver a hacer cosas en el código subyacente.

Aquí está mi ejemplo que le permitirá enlazar a una cadena que existe como una propiedad de su ventana.

public partial class Window1 : Window { public Window1() { MyString = "Here is my string"; } public string MyString { get; set; } } <Button Content="Test Button" Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}"> <Button.ContextMenu> <ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}" > <MenuItem Header="{Binding MyString}"/> </ContextMenu> </Button.ContextMenu> </Button>

La parte más importante es la etiqueta en el botón (aunque puede establecer fácilmente el DataContext del botón). Esto almacena una referencia a la ventana principal. El ContextMenu es capaz de acceder a esto a través de su propiedad PlacementTarget. A continuación, puede pasar este contexto a través de los elementos del menú.

Admitiré que esta no es la solución más elegante del mundo. Sin embargo, es mejor configurar cosas en el código detrás. Si alguien tiene una forma aún mejor de hacer esto, me encantaría escucharlo.


Por debajo:
PlacementTarget es el control que posee el ContextMenu (por ejemplo, DataGrid). No hay necesidad de una propiedad de "etiqueta".

IsEnabled se une al valor "myProperty" de DataGrid.

Probé esto y funciona. Estaba teniendo un problema similar con la unión.

<ContextMenu DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}" IsEnabled="{Binding myProperty}" >