2012-07-04 29 views
6

Esto parece ser un tema bastante popular, pero ...¿Cómo acceder a un control desde un elemento de menú ContextMenu a través del árbol visual?

Tengo el siguiente XAML:

<internal:MyCommandObject x:Name="CommandModel"/> 

<Button DockPanel.Dock="Bottom" Command="{Binding DoAction, ElementName=CommandModel}"> 
    <Button.ContextMenu> 
     <ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}"> 
      <MenuItem Command="{Binding DoAction, ElementName=CommandModel}"/> 
     </ContextMenu> 
    </Button.ContextMenu> 
    Click Me 
</Button> 

Ahora, MyCommandObject es un control que expone los comandos dinámicos de su DataContext. Ya sabes lo que vendrá después. :)

Básicamente, el comando del botón funciona perfectamente: cuando hago clic en él, el comando DoAction en el MyCommandObject se ejecuta perfectamente. Sin embargo, el comando en el elemento de menú no se ejecuta. He intentado varios trucos, como configurar el menú contextual datacontext para que sea el placementTarget, de modo que pueda atravesar el árbol visual de los controles y demás, pero no ocurre nada.

¿Qué alineación particular de las runas RelativeSource y CommandTarget necesito para que funcione?

Respuesta

4

Esto sucede porque la unión DataContext="{Binding PlacementTarget,... fijaría el botón como MenuItems DataContext, pero eso no va a añadir el ContextMenu a la VisualTree de la ventana y por eso ElementName de encuadernación no funcionarán. Una solución sencilla de utilizar ElementName fijaciones es agregar esto en su ventana/de código subyacente de control de usuario:

NameScope.SetNameScope(contextMenuName, NameScope.GetNameScope(this)); 

Otra solución es hacer esto -

<ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}"> 
    <MenuItem Command="{Binding DataContext.DoAction}"/> 
</ContextMenu> 

DataContext="{Binding PlacementTarget,... establecerá el botón (Placementtarget) como el DataContext de su ContextMenu, por lo que puede usar el DataContext de Button para enlazar el comando.

Actualización:

se puede tratar de utilizar la NameScope.NameScope Attached Property para establecer NameScope en XAML, pero no estoy seguro de cómo va a llegar el NameScope de ventana padre sin el código!

Tendrá que hacer algo similar al siguiente artículo de Josh Smith, él proporciona una forma de hacer esto en XAML; pero eso también implica código (más que eso sola línea de código) -

Enable ElementName Bindings with ElementSpy

algún motivo específico para no usar esta sola línea de código?

+0

Gracias por esto. Estoy tratando de no utilizar el código subyacente si es posible. ¿Es posible definir NameScope en XAML? Desafortunadamente, no puedo establecer el contexto de datos del elemento del menú como el botón que expone el comando. Este es un menú contextual para una grilla, y necesito el DataContext del ítem seleccionado para poder pasar propiedades de eso como parámetros al comando. – Webreaper

+0

La razón por la que no se utiliza el código subyacente es que no se compila el xaml: todo se hace en el cliente en tiempo de ejecución utilizando el enlace tardío. – Webreaper

+1

@Webreaper No estoy seguro de si está hablando solo de su escenario o en general, pero la mayoría de los archivos XAML están compilados en BAML en el momento de la compilación (mirando su xaml que también se ve en el caso); Le sugiero que consulte estos enlaces: [XAML compilado = BAML no IL] (http://blogs.microsoft.co.il/blogs/tomershamam/archive/2007/05/25/Compiled-XAML-\_3D00\_ -BAML-not-IL.aspx) y [B es para ... BAML] (http://blogs.msdn.com/b/jimoneil/archive/2009/01/12/b-is-for-baml.aspx) – akjoshi

Cuestiones relacionadas