page.DataContext не наследуется от родительского фрейма? - PullRequest
20 голосов
/ 01 сентября 2010

У меня есть страница page в рамке frame, с frame.DataContext = "foo".

  • (page.Parent as Frame).DataContext - это "foo". OK
  • BindingExpression для page.DataContext равно null (также принудительно с ClearValue). OK
  • page.DataContext - это null. но я ожидал "фу"!

Почему DataContext не наследуется? Насколько я понимаю Рамка песочницы содержание. Но я не смог найти никаких документов об этом поведении - кто-нибудь может указать мне место, где это упоминается?

Ответы [ 3 ]

27 голосов
/ 04 сентября 2010

Вы специально не спрашивали , как вы могли бы сделать эту работу, только , почему по умолчанию этого не происходит.Однако если вы хотите, чтобы ваши Страницы наследовали DataContext фрейма, вы можете сделать это:

В XAML:

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

В коде позади:

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;
}
18 голосов
/ 04 сентября 2010

Чтобы ответить на ваш вопрос о документировании этого поведения: это не документация Microsoft, но у меня есть пара книг WPF, в которых оба упоминают об этом.

« Основа Windows Presentation Foundation » гласит: (стр. 160-161)

Существуют две интересные модели для размещения судоходного контента: изолированный хостинг и интегрированный хостинг.

При изолированном хостинге контент не является доверенным и работает в полностью изолированной (изолированной) среде. Вот как содержимое WPF размещается при запуске в системном веб-браузере в качестве приложения браузера XAML. Для перехода к другому приложению или контенту HTML эта модель изолированного хостинга поддерживается с объектом Frame.

Интегрированный хостинг, , в котором мы хотим, чтобы контент работал как часть нашего приложения, в системе вообще не поддерживается. Когда Frame переходит к контенту в приложении, мы получаем странный гибрид изолированного и интегрированного поведения. Frame изолирует его содержимое от его стиля (и стиля его родителя), но не от стиля приложения. События не всплывают из контента в Frame; однако объекты доступны из свойства Content (это означает, что они не изолированы в смысле безопасности).

По всем этим причинам Frame наиболее полезен, когда мы работаем с внешним контентом, но его можно осторожно использовать для контента приложения.

Это все, что нужно сказать - ничего о наследовании имущества.

" Windows Presentation Foundation Unleashed говорит (стр. 95):

Элемент управления Frame содержит произвольный контент, как и все другие элементы управления контентом, но он изолирует контент от остального пользовательского интерфейса. Например, свойства, которые обычно наследуются в дереве элементов, останавливаются при достижении значения Frame.

.
2 голосов
/ 17 октября 2016

Чтобы развить ответ @ Joe-White для тех, кто хочет знать, как сделать Frame каскад DataContext, я упомяну, что это также может быть выполнено только в 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>

Для тех, кто не знаком с WPF, вы можете поместить этот XAML в файл App.xaml, чтобы он переопределял все элементы управления Frame в вашем приложении, которые выбирают стиль по умолчанию.Это означает, что вам не нужно писать конкретный код каждый раз, когда вы используете новый Frame.

. Я использовал Visual Design Studio 2015 Visual Designer (см. Рис. Ниже), чтобы создать большую часть XAML выше изатем добавил DataContext="{TemplateBinding DataContext}" для выполнения каскада.

VS2015 designer

...