2010-09-01 8 views
12

Tengo una Página page en un Marco frame, con frame.DataContext = "foo".page.DataContext no heredado del marco principal?

  • (page.Parent as Frame).DataContext es "foo". ok
  • BindingExpression para page.DataContext es null (también forzado con ClearValue). ok
  • page.DataContext es null. pero esperaba "foo"!

¿Por qué no se hereda el DataContext? En cuanto a I understand el marco sandboxes el contenido. Pero no pude encontrar ninguna documentación de este comportamiento. ¿Puede alguien señalarme un lugar donde se menciona esto?

+0

El BindingExpresion no se pasa sobre el tema a los niños, pero el DataContext es. ¿Revisaste la propiedad DataContext en sí? – Carlo

+0

Sí, DataContext también es nulo. Sigue siendo 'nulo' incluso después de llamar a ClearValue también. –

+0

Gracias por preguntar esto: 0) Como nota cambiar el contexto de datos del control de usuario que aloja el marco después de que todo se haya cargado (* después de * el evento cargado) hace que la página herede el nuevo contexto de datos (tiene que anular borrar y volver a establecerlo original, o no establecido hasta después de que el evento cargado haya terminado). – paulecoyote

Respuesta

12

Para responder a su pregunta sobre la documentación de este comportamiento: No es documentación de Microsoft, pero tengo un par de libros de WPF que mencionan esto.

"Essential Windows Presentation Foundation" dice: (pp 160-161.)

Hay dos modelos interesantes para alojamiento de contenidos navegable: aislados hosting y alojamiento integrada.

Con hosting aislado el contenido no es de confianza y se ejecuta en un entorno completamente aislado (espacio aislado). Así es como se aloja el contenido WPF cuando se ejecuta en el navegador web del sistema como una aplicación de navegador XAML. Para navegar a otra aplicación o contenido HTML, este modelo de alojamiento aislado es compatible con un objeto Frame.

El alojamiento integrado, en el que queremos que el contenido se comporte como parte de nuestra aplicación, no es compatible en absoluto en el sistema. Cuando Frame navega hacia el contenido dentro de la aplicación, obtenemos un extraño híbrido de comportamiento aislado e integrado. Frame aísla su contenido de su estilo (y el estilo de sus padres), pero no del estilo de la aplicación. Los eventos no burbujean desde el contenido en Frame; sin embargo, se puede acceder a los objetos desde la propiedad Content (lo que significa que no están aislados en un sentido de seguridad).

Por todas estas razones, Frame es más útil cuando trabajamos con contenido externo, pero se puede usar con cuidado para el contenido de la aplicación.

Eso es todo lo que tiene que decir, nada sobre la herencia de la propiedad.

"Windows Presentation Foundation Unleashed dice (p 95).:.

El control Frame sostiene contenido arbitrario, al igual que todos los demás controles de contenido, pero que aísla el contenido del resto de la interfaz de usuario, por ejemplo, propiedades que normalmente se heredarían en la parada del árbol de elementos cuando alcancen el Frame.

21

Usted no pidió específicamente cómo se podría hacer este trabajo, sólo se por qué no lo hace por defecto. Sin embargo, si usted quiere que sus páginas para heredar DataContext del marco, usted puede hacer esto:

En XAML:

<Frame Name="frame" 
     LoadCompleted="frame_LoadCompleted" 
     DataContextChanged="frame_DataContextChanged"/> 

En CodeBehind:

private void frame_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) 
{ 
    UpdateFrameDataContext(sender, e); 
} 
private void frame_LoadCompleted(object sender, NavigationEventArgs e) 
{ 
    UpdateFrameDataContext(sender, e); 
} 
private void UpdateFrameDataContext(object sender, NavigationEventArgs e) 
{ 
    var content = frame.Content as FrameworkElement; 
    if (content == null) 
     return; 
    content.DataContext = frame.DataContext; 
} 
+0

Funciona como debería :) Gracias. – torpederos

1

Para aprovechar @ Joe-Blanco de Para aquellos que quieran saber cómo hacer la cascada Frame en el DataContext, mencionaré que esto también se puede realizar solo en XAML.

<Style TargetType="{x:Type Frame}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type Frame}"> 
        <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"> 
         <ContentPresenter x:Name="PART_FrameCP" DataContext="{TemplateBinding DataContext}"/> 
        </Border> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
     <Style.Triggers> 
      <Trigger Property="NavigationUIVisibility" Value="Visible"> 
       <Setter Property="Template" Value="{StaticResource FrameNavChromeTemplateKey}"/> 
      </Trigger> 
      <MultiTrigger> 
       <MultiTrigger.Conditions> 
        <Condition Property="JournalOwnership" Value="OwnsJournal"/> 
        <Condition Property="NavigationUIVisibility" Value="Automatic"/> 
       </MultiTrigger.Conditions> 
       <Setter Property="Template" Value="{StaticResource FrameNavChromeTemplateKey}"/> 
      </MultiTrigger> 
     </Style.Triggers> 
    </Style> 

Para aquellos que son nuevos en WPF, puede poner esto en el archivo XAML App.xaml para que anulará todos Frame controles de la aplicación que recogen el estilo por defecto. Esto significa que no tiene que escribir detrás de códigos específicos cada vez que usa un nuevo Frame.

Utilicé el VisualStudio 2015 Visual Designer (ver imagen a continuación) para crear la mayor parte del XAML anterior y luego agregué el DataContext="{TemplateBinding DataContext}" para realizar la cascada.

VS2015 designer

+0

No funcionó para mí. Recibí una excepción "No se pudo incluir el objeto de tipo 'MS.Internal.NamedObject' para escribir 'System.Windows.FrameworkTemplate'. – denver

Cuestiones relacionadas