2010-09-01 8 views
12

Ho una Pagina page in un Frame frame, con frame.DataContext = "foo".page.DataContext non ereditata dal frame principale?

  • (page.Parent as Frame).DataContext è "foo". ok
  • BindingExpression per page.DataContext è null (anche forzato con ClearValue). ok
  • page.DataContext è null. ma mi aspettavo "foo"!

Perché il DataContext non è ereditato? Per quanto riguarda I understand le sandbox Frame il contenuto. Ma non sono riuscito a trovare alcuna documentazione di questo comportamento: qualcuno può indicarmi un luogo in cui viene menzionato?

+0

Il BindingExpresion non è passata sopra alla voce del bambino, ma il DataContext è. Hai controllato la proprietà DataContext stessa? – Carlo

+0

Sì, DataContext è anche null. Rimane 'nullo' anche dopo aver chiamato ClearValue su di esso. –

+0

Grazie per avermelo chiesto: 0) Come nota, cambiare il datacontext dal controllo utente che ospita il frame dopo che tutto è stato caricato (* dopo * l'evento caricato) fa sì che la pagina erediti il ​​nuovo datacontext (devi annullare e reimpostare originale o non impostato fino a quando l'evento caricato non è terminato). – paulecoyote

risposta

12

Per rispondere alla domanda sulla documentazione di questo comportamento: Non è la documentazione Microsoft, ma ho un paio di libri WPF che menzionano entrambi.

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

Ci sono due modelli interessanti per l'hosting di contenuti navigabile: isolati hosting e hosting integrata.

Con hosting isolato il contenuto non è affidabile ed è eseguito in un ambiente completamente isolato (in modalità sandbox). Questo è il modo in cui il contenuto WPF è ospitato durante l'esecuzione nel browser Web di sistema come applicazione browser XAML. Per la navigazione verso un'altra applicazione o contenuto HTML, questo modello di hosting isolato è supportato con un oggetto Frame.

L'hosting integrato, in cui si desidera che il contenuto si comporti come parte della nostra applicazione, non è supportato affatto nel sistema. Quando Frame si sposta verso il contenuto all'interno dell'applicazione, otteniamo uno strano ibrido di comportamento isolato e integrato. Frame isola il suo contenuto dal suo stile (e dallo stile del suo genitore), ma non dallo stile dell'applicazione. Gli eventi non scoppiano dal contenuto di Frame; tuttavia, gli oggetti sono accessibili dalla proprietà Content (ovvero non sono isolati in senso di sicurezza).

Per tutti questi motivi, Frame è molto utile quando si lavora con contenuti esterni, ma può essere utilizzato con attenzione per il contenuto dell'applicazione.

Questo è tutto ciò che ha da dire: niente sull'eredità della proprietà.

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

Il controllo Frame tiene contenuto arbitrario, proprio come tutti gli altri controlli di contenuto, ma isola il contenuto dal resto dell'interfaccia utente, ad esempio, le proprietà che sarebbe normalmente ereditato dalla fermata dell'albero degli elementi quando raggiungono lo Frame.

21

Non ha specificamente chiedere come si potrebbe fare questo lavoro, solo perché non è così per impostazione predefinita. Tuttavia, se si desidera che le pagine ereditare DataContext della cornice, si può fare questo:

In XAML:

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

In 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

Funziona come dovrebbe :) Grazie. – torpederos

1

Per costruire su @ Joe-White risposta per coloro che vogliono sapere come renderea cascata il DataContext, menzionerò che questo può essere eseguito anche in 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> 

Per coloro che sono nuovi per WPF, si può mettere questo nel file XAML App.xaml in modo che avrà la precedenza su tutte le Frame controlli nell'applicazione che riprendono lo stile predefinito. Ciò significa che non è necessario scrivere codice specifico ogni volta che si utilizza un nuovo Frame.

Ho utilizzato VisualStudio 2015 Visual Designer (vedere la figura sotto) per creare la maggior parte dello XAML sopra e quindi aggiunto DataContext="{TemplateBinding DataContext}" per eseguire la cascata.

VS2015 designer

+0

Non ha funzionato per me. Ho ricevuto un'eccezione "Impossibile inserire l'oggetto caso di tipo" MS.Internal.NamedObject "per digitare" System.Windows.FrameworkTemplate ". – denver

Problemi correlati