@ -101,6 +101,7 @@ namespace Avalonia.Controls
private Styles _ styles ;
private bool _ styled ;
private Subject < IStyleable > _ styleDetach = new Subject < IStyleable > ( ) ;
private bool _d ataContextUpdating ;
/// <summary>
/// Initializes static members of the <see cref="Control"/> class.
@ -111,6 +112,7 @@ namespace Avalonia.Controls
PseudoClass ( IsEnabledCoreProperty , x = > ! x , ":disabled" ) ;
PseudoClass ( IsFocusedProperty , ":focus" ) ;
PseudoClass ( IsPointerOverProperty , ":pointerover" ) ;
DataContextProperty . Changed . AddClassHandler < Control > ( x = > x . OnDataContextChangedCore ) ;
}
/// <summary>
@ -681,18 +683,26 @@ namespace Avalonia.Controls
}
/// <summary>
/// Called before the <see cref="DataContext"/> property changes.
/// Called when the <see cref="DataContext"/> property changes.
/// </summary>
protected virtual void OnDataContextChanging ( )
/// <param name="e">The event args.</param>
protected virtual void OnDataContextChanged ( EventArgs e )
{
DataContextChanged ? . Invoke ( this , EventArgs . Empty ) ;
}
/// <summary>
/// Called after the <see cref="DataContext"/> property changes .
/// Called when the <see cref="DataContext"/> begins updating .
/// </summary>
protected virtual void OnDataContextChanged ( )
protected virtual void OnDataContextBeginUpdate ( )
{
}
/// <summary>
/// Called when the <see cref="DataContext"/> finishes updating.
/// </summary>
protected virtual void OnDataContextEndUpdate ( )
{
DataContextChanged ? . Invoke ( this , EventArgs . Empty ) ;
}
/// <inheritdoc/>
@ -745,24 +755,38 @@ namespace Avalonia.Controls
}
}
/// <summary>
/// Called when the <see cref="DataContext"/> property begins and ends being notified.
/// </summary>
/// <param name="o">The object on which the DataContext is changing.</param>
/// <param name="notifying">Whether the notifcation is beginning or ending.</param>
private static void DataContextNotifying ( IAvaloniaObject o , bool notifying )
{
var control = o as Control ;
if ( o is Control control )
{
DataContextNotifying ( control , notifying ) ;
}
}
if ( control ! = null )
private static void DataContextNotifying ( Control control , bool notifying )
{
if ( notifying )
{
if ( notifying )
if ( ! control . _d ataContextUpdat ing)
{
control . OnDataContextChanging ( ) ;
control . _d ataContextUpdating = true ;
control . OnDataContextBeginUpdate ( ) ;
foreach ( var child in control . LogicalChildren )
{
if ( child is Control c & & ! c . IsSet ( DataContextProperty ) )
{
DataContextNotifying ( c , notifying ) ;
}
}
}
else
}
else
{
if ( control . _d ataContextUpdating )
{
control . OnDataContextChanged ( ) ;
control . OnDataContextEndUpdate ( ) ;
control . _d ataContextUpdating = false ;
}
}
}
@ -881,6 +905,11 @@ namespace Avalonia.Controls
}
}
private void OnDataContextChangedCore ( AvaloniaPropertyChangedEventArgs e )
{
OnDataContextChanged ( EventArgs . Empty ) ;
}
private void LogicalChildrenCollectionChanged ( object sender , NotifyCollectionChangedEventArgs e )
{
switch ( e . Action )