WPF:为什么没有在逻辑子上引发DataContextChanged?

Dan*_*bić 2 wpf datacontext logical-tree

我有一个问题,DataContextChanged没有在我的自定义Panel控件的逻辑子上引发.我把它缩小到这个:

从向导生成的WPF应用程序开始,我添加:

    private void Window_Loaded( object sender, RoutedEventArgs e )
    {
        var elt = new FrameworkElement();
        this.AddLogicalChild( elt );
        DataContext = 42;
        Debug.Assert( (int)elt.DataContext == 42 );
    }
Run Code Online (Sandbox Code Playgroud)

据我所知,这是有效的,因为DataContext是一个可继承的依赖属性.

现在,我在Window(this)及其逻辑子代上为DataContextChanged添加事件处理程序:

    this.DataContextChanged += 
        delegate { Debug.WriteLine( "this:DataContextChanged" ); };
    elt.DataContextChanged += 
        delegate { Debug.WriteLine( "elt:DataContextChanged" ); };
Run Code Online (Sandbox Code Playgroud)

如果我运行它,只会执行第一个事件处理程序.为什么是这样?如果不是AddLogicalChild(elt),我会执行以下操作:

this.Content = elt;
Run Code Online (Sandbox Code Playgroud)

两个处理程序都将执行.但是在我的情况下这不是一个选项 - 我正在向我的控件中添加FrameworkContentElements,它们不应该是可视化的孩子.

这里发生了什么?除了AddLogicalChild()之外,我还应该做些什么来使它工作吗?

(幸运的是,有一个相当简单的解决方法 - 只需将元素的DataContext绑定到窗口的DataContext)

BindingOperations.SetBinding( elt, FrameworkElement.DataContextProperty, 
            new Binding( "DataContext" ) { Source = this } );
Run Code Online (Sandbox Code Playgroud)

谢谢.

Ken*_*art 6

您还需要覆盖该LogicalChildren属性:

protected override System.Collections.IEnumerator LogicalChildren
{
    get { yield return elt; }
}
Run Code Online (Sandbox Code Playgroud)

当然,您也希望返回由基本实现定义的任何逻辑子代.