【问题标题】:page.DataContext not inherited from parent Frame?page.DataContext 不是从父框架继承的?
【发布时间】:2011-04-06 23:47:50
【问题描述】:

我在框架frame 中有一个页面page,带有frame.DataContext = "foo"

  • (page.Parent as Frame).DataContext"foo"好的
  • page.DataContext 的 BindingExpression 是 null(也强制使用 ClearValue)。 好的
  • page.DataContextnull但我期待的是“foo”!

为什么不继承 DataContext?至于我understand Frame sandboxes 的内容。但我找不到任何关于这种行为的文档 - 谁能指出我提到的地方?

【问题讨论】:

  • BindingExpresion 不会传递给子项,但 DataContext 是。您是否检查了 DataContext 属性本身?
  • 是的,DataContext 也是空的。它仍然是null,即使在调用 ClearValue 之后也是如此。
  • 感谢您提出这个问题 :0) 作为注释,在所有内容加载后(加载事件之后)从承载框架的用户控件更改数据上下文会导致页面继承新的数据上下文(必须清空并将其设置回原始数据,或者直到加载的事件完成后才设置)。

标签: c# wpf binding datacontext msdn


【解决方案1】:

你并没有特别问如何你可以做到这一点,只是为什么默认情况下它不会。但是,如果您确实希望您的 Pages 继承 Frame 的 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;
}

【讨论】:

  • 工作正常 :) 谢谢。
【解决方案2】:

回答您有关此行为文档的问题:这不是 Microsoft 文档,但我有几本 WPF 书籍都提到了这一点。

Essential Windows Presentation Foundation”说:(第 160-161 页)

托管可导航内容有两种有趣的模型:独立托管和集成托管。

使用隔离托管,内容不受信任,并且在完全隔离(沙盒)的环境中运行。这就是 WPF 内容在系统 Web 浏览器中作为 XAML 浏览器应用程序运行时的托管方式。对于导航到另一个应用程序或 HTML 内容,Frame 对象支持这种独立的托管模型。

集成托管,我们希望内容作为我们应用程序的一部分在其中运行,系统根本不支持。当Frame 导航到应用程序中的内容时,我们得到了一种奇怪的孤立和集成行为的混合体。 Frame 将其内容与其样式(及其父样式)隔离,但不与应用程序的样式隔离。事件不会从Frame 中的内容冒泡;但是,可以从 Content 属性访问这些对象(这意味着它们在安全意义上不是孤立的)。

由于所有这些原因,Frame 在我们处理外部内容时最有用,但它可以小心地用于应用程序内容。

这就是它要说的全部内容——没有关于属性继承的内容。

Windows Presentation Foundation Unleashed 说(第 95 页):

Frame 控件包含任意内容,就像所有其他内容控件一样,但它将内容与 UI 的其余部分隔离开来。例如,通常沿元素树向下继承的属性在到达 Frame 时停止。

【讨论】:

    【解决方案3】:

    对于那些想知道如何使Frame 级联DataContext 的人的@Joe-White 的回答,我会提到这也只能在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 时编写特定的代码隐藏。

    我使用 VisualStudio 2015 视觉设计器(见下图)创建了上面的大部分 XAML,然后添加了DataContext="{TemplateBinding DataContext}" 来执行级联。

    【讨论】:

    • 对我不起作用。我收到一个异常“无法将'MS.Internal.NamedObject'类型的对象键入'System.Windows.FrameworkTemplate'。
    猜你喜欢
    • 2015-12-26
    • 2019-01-08
    • 2015-08-10
    • 2011-06-20
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-04
    相关资源
    最近更新 更多