@@ -265,9 +265,12 @@ static void OnTransformChanged(BindableObject bindable, object oldValue, object
265265 BindableProperty . Create ( "TransformOrigin" , typeof ( Point ) , typeof ( VisualElement ) , new Point ( .5d , .5d ) ,
266266 propertyChanged : ( b , o , n ) => { ( ( ( VisualElement ) b ) . AnchorX , ( ( VisualElement ) b ) . AnchorY ) = ( Point ) n ; } ) ;
267267
268+ bool _isVisibleExplicit = ( bool ) IsVisibleProperty . DefaultValue ;
269+
268270 /// <summary>Bindable property for <see cref="IsVisible"/>.</summary>
269271 public static readonly BindableProperty IsVisibleProperty = BindableProperty . Create ( "IsVisible" , typeof ( bool ) , typeof ( VisualElement ) , true ,
270- propertyChanged : ( bindable , oldvalue , newvalue ) => ( ( VisualElement ) bindable ) . OnIsVisibleChanged ( ( bool ) oldvalue , ( bool ) newvalue ) ) ;
272+ propertyChanged : ( bindable , oldvalue , newvalue ) => ( ( VisualElement ) bindable ) . OnIsVisibleChanged ( ( bool ) oldvalue , ( bool ) newvalue ) ,
273+ coerceValue : CoerceIsVisibleProperty ) ;
271274
272275 /// <summary>Bindable property for <see cref="Opacity"/>.</summary>
273276 public static readonly BindableProperty OpacityProperty = BindableProperty . Create ( "Opacity" , typeof ( double ) , typeof ( VisualElement ) , 1d , coerceValue : ( bindable , value ) => ( ( double ) value ) . Clamp ( 0 , 1 ) ) ;
@@ -679,6 +682,36 @@ private protected bool InputTransparentCore
679682 }
680683 }
681684
685+ /// <summary>
686+ /// This value represents the cumulative IsVisible value.
687+ /// All types that override this property need to also invoke
688+ /// the RefreshIsVisibleProperty() method if the value will change.
689+ /// </summary>
690+ private protected bool IsVisibleCore
691+ {
692+ get
693+ {
694+ if ( _isVisibleExplicit == false )
695+ {
696+ // If the explicitly set value is false, then nothing else matters
697+ // And we can save the effort of a Parent check
698+ return false ;
699+ }
700+
701+ var parent = Parent as VisualElement ;
702+ while ( parent is not null )
703+ {
704+ if ( ! parent . IsVisible )
705+ {
706+ return false ;
707+ }
708+ parent = parent . Parent as VisualElement ;
709+ }
710+
711+ return _isVisibleExplicit ;
712+ }
713+ }
714+
682715 /// <summary>
683716 /// Gets a value indicating whether this element is focused currently. This is a bindable property.
684717 /// </summary>
@@ -1426,6 +1459,7 @@ internal virtual void OnIsVisibleChanged(bool oldValue, bool newValue)
14261459 fe . Handler ? . UpdateValue ( nameof ( IView . Visibility ) ) ;
14271460 }
14281461
1462+ ( this as IPropertyPropagationController ) ? . PropagatePropertyChanged ( IsVisibleProperty . PropertyName ) ;
14291463 InvalidateMeasureInternal ( InvalidationTrigger . Undefined ) ;
14301464 }
14311465
@@ -1590,6 +1624,17 @@ static object CoerceInputTransparentProperty(BindableObject bindable, object val
15901624 return false ;
15911625 }
15921626
1627+ static object CoerceIsVisibleProperty ( BindableObject bindable , object value )
1628+ {
1629+ if ( bindable is VisualElement visualElement )
1630+ {
1631+ visualElement . _isVisibleExplicit = ( bool ) value ;
1632+ return visualElement . IsVisibleCore ;
1633+ }
1634+
1635+ return false ;
1636+ }
1637+
15931638 static void OnInputTransparentPropertyChanged ( BindableObject bindable , object oldValue , object newValue )
15941639 {
15951640 ( bindable as IPropertyPropagationController ) ? . PropagatePropertyChanged ( VisualElement . InputTransparentProperty . PropertyName ) ;
@@ -1657,6 +1702,9 @@ void IPropertyPropagationController.PropagatePropertyChanged(string propertyName
16571702 if ( propertyName == null || propertyName == InputTransparentProperty . PropertyName )
16581703 this . RefreshPropertyValue ( InputTransparentProperty , _inputTransparentExplicit ) ;
16591704
1705+ if ( propertyName == null || propertyName == IsVisibleProperty . PropertyName )
1706+ this . RefreshPropertyValue ( IsVisibleProperty , _isVisibleExplicit ) ;
1707+
16601708 PropertyPropagationExtensions . PropagatePropertyChanged ( propertyName , this , ( ( IVisualTreeElement ) this ) . GetVisualChildren ( ) ) ;
16611709 }
16621710
@@ -1667,6 +1715,13 @@ void IPropertyPropagationController.PropagatePropertyChanged(string propertyName
16671715 protected void RefreshIsEnabledProperty ( ) =>
16681716 this . RefreshPropertyValue ( IsEnabledProperty , _isEnabledExplicit ) ;
16691717
1718+ /// <summary>
1719+ /// This method must always be called if some event occurs and the value of
1720+ /// the <see cref="IsVisibleCore"/> property will change.
1721+ /// </summary>
1722+ protected void RefreshIsVisibleProperty ( ) =>
1723+ this . RefreshPropertyValue ( IsVisibleProperty , _isVisibleExplicit ) ;
1724+
16701725 /// <summary>
16711726 /// This method must always be called if some event occurs and the value of
16721727 /// the InputTransparentCore property will change.
0 commit comments