@ -10,6 +10,8 @@ namespace Avalonia.PropertyStore
{
private readonly ValueStore _ owner ;
private IDisposable ? _ subscription ;
private T ? _d efaultValue ;
private bool _ isDefaultValueInitialized ;
public LocalValueBindingObserver ( ValueStore owner , StyledProperty < T > property )
{
@ -41,26 +43,28 @@ namespace Avalonia.PropertyStore
public void OnNext ( T value )
{
static void Execute ( ValueStore owner , StyledProperty < T > property , T value )
static void Execute ( LocalValueBindingObserver < T > instance , T value )
{
if ( property . ValidateValue ? . Invoke ( value ) ! = false )
owner . SetValue ( property , value , BindingPriority . LocalValue ) ;
else
owner . ClearLocalValue ( property ) ;
var owner = instance . _ owner ;
var property = instance . Property ;
if ( property . ValidateValue ? . Invoke ( value ) = = false )
value = instance . GetCachedDefaultValue ( ) ;
owner . SetValue ( property , value , BindingPriority . LocalValue ) ;
}
if ( Dispatcher . UIThread . CheckAccess ( ) )
{
Execute ( _ owner , Property , value ) ;
Execute ( this , value ) ;
}
else
{
// To avoid allocating closure in the outer scope we need to capture variables
// locally. This allows us to skip most of the allocations when on UI thread.
var instance = _ owner ;
var property = Property ;
var instance = this ;
var newValue = value ;
Dispatcher . UIThread . Post ( ( ) = > Execute ( instance , property , newValue ) ) ;
Dispatcher . UIThread . Post ( ( ) = > Execute ( instance , newValue ) ) ;
}
}
@ -73,12 +77,13 @@ namespace Avalonia.PropertyStore
LoggingUtils . LogIfNecessary ( owner . Owner , property , value ) ;
if ( value . HasValue )
owner . SetValue ( property , value . Value , BindingPriority . LocalValue ) ;
else if ( value . Type ! = BindingValueType . DataValidationError )
owner . ClearLocalValue ( property ) ;
var effectiveValue = value . HasValue ? value . Value : instance . GetCachedDefaultValue ( ) ;
owner . SetValue ( property , effectiveValue , BindingPriority . LocalValue ) ;
}
if ( value . Type is BindingValueType . DoNothing or BindingValueType . DataValidationError )
return ;
if ( Dispatcher . UIThread . CheckAccess ( ) )
{
Execute ( this , value ) ;
@ -92,5 +97,16 @@ namespace Avalonia.PropertyStore
Dispatcher . UIThread . Post ( ( ) = > Execute ( instance , newValue ) ) ;
}
}
private T GetCachedDefaultValue ( )
{
if ( ! _ isDefaultValueInitialized )
{
_d efaultValue = Property . GetDefaultValue ( _ owner . Owner . GetType ( ) ) ;
_ isDefaultValueInitialized = true ;
}
return _d efaultValue ! ;
}
}
}