WPF: Почему DataContextChanged не вызывается на логическом дочернем элементе? - PullRequest
2 голосов
/ 07 апреля 2009

У меня проблема с 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 );
    }

Как я понимаю, это работает, потому что DataContext является наследуемым свойством зависимости .

Теперь я добавляю обработчики событий для DataContextChanged как в окне (это), так и в его логическом дочернем элементе:

    this.DataContextChanged += 
        delegate { Debug.WriteLine( "this:DataContextChanged" ); };
    elt.DataContextChanged += 
        delegate { Debug.WriteLine( "elt:DataContextChanged" ); };

Если я запускаю это, будет выполняться только первый обработчик события . Почему это так? Если вместо AddLogicalChild (elt) я делаю следующее:

this.Content = elt;

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

Что здесь происходит? Должен ли я сделать что-то еще, кроме AddLogicalChild (), чтобы это работало?

(К счастью, существует довольно простой обходной путь - просто свяжите DataContext элемента с DataContext окна)

BindingOperations.SetBinding( elt, FrameworkElement.DataContextProperty, 
            new Binding( "DataContext" ) { Source = this } );

Спасибо.

1 Ответ

5 голосов
/ 07 апреля 2009

Вам также необходимо переопределить свойство LogicalChildren:

protected override System.Collections.IEnumerator LogicalChildren
{
    get { yield return elt; }
}

Конечно, вы также захотите вернуть любые логические дочерние элементы, определенные базовой реализацией.

...