【问题标题】:WPF DataContext works differently in seemingly identical situationsWPF DataContext 在看似相同的情况下工作方式不同
【发布时间】:2017-02-25 13:46:24
【问题描述】:

我有以下资源:

<Window.Resources>
    <SolidColorBrush x:Key="b" Color="{Binding B}" />
    <my:C x:Key="c" Prop="{Binding Source={StaticResource b}}" />
    <my:C x:Key="d" Prop="{Binding A}" />
    <Ellipse x:Key="e" Fill="{Binding A}" />
    <Ellipse x:Key="f">
        <Ellipse.Fill>
            <SolidColorBrush Color="{Binding B}" />
        </Ellipse.Fill>
    </Ellipse>
</Window.Resources>

我的窗口有一个这样声明的数据上下文:

<Window ... DataContext="{my:Context}" ...>

自定义类 C 和 Context 定义如下:

public class Context : MarkupExtension
{
    public Brush A { get; } = Brushes.Blue;
    public Color B { get; } = Colors.Red;

    public override object ProvideValue(IServiceProvider serviceProvider) => this;
}

public class C : DependencyObject
{
    public static readonly DependencyProperty PropProperty = DependencyProperty.Register("Prop", typeof(Brush), typeof(C));
    public Brush Prop { get { return (Brush)GetValue(PropProperty); } set { SetValue(PropProperty, value); } }
}

现在,我使用数据上下文和绑定的方式似乎与我非常相似,但如果我使用以下代码检查我的资源(在按钮单击处理程序内)

MessageBox.Show("f: " + ((FindResource("f") as Ellipse).Fill?.ToString() ?? "null"));
MessageBox.Show("e: " + ((FindResource("e") as Ellipse).Fill?.ToString() ?? "null"));
MessageBox.Show("d: " + ((FindResource("d") as C).Prop?.ToString() ?? "null"));
MessageBox.Show("c: " + ((FindResource("c") as C).Prop?.ToString() ?? "null"));
MessageBox.Show("b: " + (FindResource("b") as SolidColorBrush).Color.ToString());

我得到这个结果:

f: #00FFFFFF
e: null
d: null
c: #FFFF0000
b: #FFFF0000

即只有最后两个看似正确。这可能是什么原因?

【问题讨论】:

    标签: c# wpf data-binding datacontext


    【解决方案1】:

    我对此很好奇,所以决定试一试。我远不是 XAML 方面的专家,但我想分享我的发现以防万一。

    我将以下 XAML 添加到页面上的 Grid

    <Ellipse Fill="{StaticResource b}" />
    <Ellipse Grid.Row="1" Fill="{Binding Source={StaticResource c}, Path=Prop}" />
    <Ellipse Grid.Row="2" Fill="{Binding Source={StaticResource d}, Path=Prop}" />
    <ContentControl Grid.Row="3" Content="{StaticResource e}" />
    <ContentControl Grid.Row="4" Content="{StaticResource f}" />
    

    这是结果的截图:

    Output 窗口出现以下绑定错误,我想这解释了为什么d 没有被填充:

    System.Windows.Data 错误:2:找不到管理 FrameworkElement 或 FrameworkContentElement 为目标元素。 绑定表达式:路径=A;数据项=空;目标元素是'C' (哈希码=60275915);目标属性是“道具”(类型“画笔”)

    看起来它可能无法解析 d 的绑定,因为它无法定位其在元素层次结构中的位置,因此无法解析 DataContext。

    我还注意到,如果我将 XAML 注释掉,则行为与问题中发布的完全相同。 ed 都为空。基于此,似乎资源的使用可能会影响绑定是否可以在运行时解决。

    很高兴听到有人更深入地了解绑定如何在资源中发挥作用的内部工作原理。

    【讨论】:

      【解决方案2】:

      奇怪。

      my:C 显然没有 DataContext,因此不能直接绑定到任何东西。

      具有 DataContext 的资源不继承资源所有者的 DataContext(省略号 e 和 f)

      SolidColorBrush "b" 派生自 System.Windows.Freezable,它有一个名为 InheritanceContext 的受保护字段/属性,对于 "b",它设置为 MainWindow。我认为它可以通过这个引用访问 Context.B,这就是“b”和“c”显示正确颜色的原因。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-11-08
        • 1970-01-01
        • 2018-12-06
        • 1970-01-01
        • 2013-10-17
        • 1970-01-01
        相关资源
        最近更新 更多